ContactsProvider2.java revision a6733943584294492aa0118fc32bf4e58dabb028
14f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/* 24f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Copyright (C) 2009 The Android Open Source Project 34f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 44f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 54f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * you may not use this file except in compliance with the License. 64f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * You may obtain a copy of the License at 74f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 84f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 94f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Unless required by applicable law or agreed to in writing, software 114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * See the License for the specific language governing permissions and 144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * limitations under the License 154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts; 1828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar 1967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport com.android.internal.content.SyncStateContentProviderHelper; 205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 21e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.AggregatedPresenceColumns; 2228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.AggregationExceptionColumns; 2328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.Clauses; 24d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.ContactsColumns; 2528f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.DataColumns; 2628f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.GroupsColumns; 2728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.MimetypesColumns; 2811944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.NameLookupColumns; 295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.NameLookupType; 3067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport com.android.providers.contacts.OpenHelper.PackagesColumns; 31d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.PhoneColumns; 3228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.PhoneLookupColumns; 334dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.PresenceColumns; 34d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.RawContactsColumns; 3528f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.Tables; 36e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikovimport com.google.android.collect.Lists; 37e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 38b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 39caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 40c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 41568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 42568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 4335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 4467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 4567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 4635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.Entity; 4767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.EntityIterator; 48568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 493d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 5067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences.Editor; 52b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 54ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 55b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 56b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 59c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 61b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 63508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 64de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract; 651b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikovimport android.provider.LiveFolders; 66b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 67de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds; 68d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 69de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Data; 70ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Groups; 71e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 721f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkeyimport android.provider.ContactsContract.Presence; 73d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 74eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkeyimport android.provider.ContactsContract.Settings; 753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 76ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 77ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 81de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 82b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 834097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 8467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 85a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 86a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 87c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 89b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 92b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 94ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 100de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikovpublic class ContactsProvider2 extends SQLiteContentProvider { 101caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 102b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey // TODO: clean up debug tag and rename this class 103b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey private static final String TAG = "ContactsProvider ~~~~"; 1044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 105619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 106619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 107619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1113d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1123d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1133d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1143d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1153d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1163d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1173d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1183d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 119a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 121d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 122d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.TIMES_CONTACTED + " DESC, " 123d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.DISPLAY_NAME + " ASC"; 124d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 125d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 126d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 127d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 128d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 129d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 1384f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 1424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1436bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1446bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 145ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 146ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES_FILTER = 3003; 1474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final int EMAILS = 3004; 1484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final int EMAILS_FILTER = 3005; 1494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final int POSTALS = 3006; 150a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1516bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1526bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 153b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 154b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 155b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 1561f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE = 7000; 1571f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE_ID = 7001; 1581f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 15931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 16031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 161eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 162eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 163ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 164ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 165ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 166ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 16735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 16835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 169c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 170c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 171c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 172a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov private static final int DATA_WITH_PRESENCE = 13000; 17319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 1741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 1751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 1761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 1771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 1781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 17967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private interface ContactsQuery { 1805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final String TABLE = Tables.RAW_CONTACTS; 1819261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 18267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 1836cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 1846cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 1856cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 186ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 187ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 18967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_NAME = 1; 19067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_TYPE = 2; 19167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 19267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 193d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 194d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final String TABLE = Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS; 19567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 19667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 1976cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 1983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 199d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.CONCRETE_ID, 2003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.CONCRETE_ID, 201ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 202ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 203d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 20467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 205d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 20667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int MIMETYPE_ID = 3; 207ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private interface DisplayNameQuery { 21067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final String[] COLUMNS = new String[] { 2133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 2153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA2, 2163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov StructuredName.DISPLAY_NAME, 2173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 0; 2203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 1; 2213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA2 = 2; 2223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DISPLAY_NAME = 3; 2233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 22514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 22667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 22888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2315ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 2333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA2, 23488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 23588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 23688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 23788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 23888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 23988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 24088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 24188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.DATA2, 2423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 24414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 24888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final int DATA2 = 4; 2493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 25114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 252321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 25320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 25420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 255321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 256321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 25720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 25820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov // Higher number represents higher priority in choosing what data to use for the display name 2603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_EMAIL = 1; 2613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_PHONE = 2; 2623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_ORGANIZATION = 3; 2633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_STRUCTURED_NAME = 4; 2643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final HashMap<String, Integer> sDisplayNamePriorities; 2663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov static { 2673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities = new HashMap<String, Integer>(); 2683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(StructuredName.CONTENT_ITEM_TYPE, 2693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_STRUCTURED_NAME); 2703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(Organization.CONTENT_ITEM_TYPE, 2713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_ORGANIZATION); 2723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(Phone.CONTENT_ITEM_TYPE, 2733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_PHONE); 2743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(Email.CONTENT_ITEM_TYPE, 2753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_EMAIL); 2763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 27731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 278caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov public static final String DEFAULT_ACCOUNT_TYPE = "com.google.GAIA"; 279df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 280caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 281038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 282038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 283e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 2844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 285ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains contacts and presence columns */ 286ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov private static final HashMap<String, String> sContactsWithPresenceProjectionMap; 287ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 288d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 2894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 2904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 2919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 292e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 293ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 294ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 295ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 296ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 297373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 298b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 299eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 300eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 301373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains Presence columns */ 302373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov private static final HashMap<String, String> sPresenceProjectionMap; 30319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov /** Contains Presence columns */ 304a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov private static final HashMap<String, String> sDataWithPresenceProjectionMap; 3051b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3061b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 308b67163a1088f09c59f324350662eb18772fac6b6Evan Millar /** Sql where statement for filtering on groups. */ 309d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String sContactsInGroupSelect; 31019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 311c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 312c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 314c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 315d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Precompiled sql statement for incrementing times contacted for an contact */ 316f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private SQLiteStatement mLastTimeContactedUpdate; 3173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 3183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private SQLiteStatement mContactDisplayNameUpdate; 31973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** Precompiled sql statement for marking a raw contact as dirty */ 32073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private SQLiteStatement mRawContactDirtyUpdate; 321e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov /** Precompiled sql statement for setting an aggregated presence */ 322e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov private SQLiteStatement mAggregatedPresenceReplace; 323e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov /** Precompiled sql statement for updating an aggregated presence status */ 324e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov private SQLiteStatement mAggregatedPresenceStatusUpdate; 325a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 3264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 3274f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 328a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 329d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 330d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 331d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 3323653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 3333653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 3343653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 3355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 3365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 3375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 3385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 339ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 340ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 3415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 3423653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 3435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 3445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 3455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 346b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 3484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 349ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 350ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 3514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 3524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 353ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 3541f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 355ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 356ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 357ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 358ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 35935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 36035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 361a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 362b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 363b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 364b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 365b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 3664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 367eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 368eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 369bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence", PRESENCE); 370bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence/#", PRESENCE_ID); 3711f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 372c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 373c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 374c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 375c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 376c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 377c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 378c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3791b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 3801b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 3811b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 3821b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 3831b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 3841b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 3851b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 3861b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 3871b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 38819a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov // Private API 389a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data_with_presence", DATA_WITH_PRESENCE); 39019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 39119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 39219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 393038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 394038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 395e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 3964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 3974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 3984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 3994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 405f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 4064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 4084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 409ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap = new HashMap<String, String>(); 410ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap.putAll(sContactsProjectionMap); 411ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap.put(Contacts.PRESENCE_STATUS, 412e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov Presence.PRESENCE_STATUS + " AS " + Contacts.PRESENCE_STATUS); 413ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap.put(Contacts.PRESENCE_CUSTOM_STATUS, 414ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Presence.PRESENCE_CUSTOM_STATUS + " AS " + Contacts.PRESENCE_CUSTOM_STATUS); 4154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 4174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 4184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 4194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 4204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 4214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 4224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 4234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 4244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 4254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 4264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 4274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 4284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 4294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 4304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 4314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 4324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 4334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 4344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 4354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 4362815f58f72f109790585931f601a63ddc02536a5Evan Millar 4374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 4384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 4394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 4404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 4414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 4424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 4434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 4444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 4454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 4464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 4474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 4484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 4494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 4504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 4514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 4524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 4534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 4544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 4554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 4564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 4574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 4584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 4594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 4604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 4614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 4624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 4634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 4644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 4654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 4664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 4674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 4684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 4694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 4704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 4714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 4724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 478a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 479e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 480e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 481e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_ID + " AS " + PhoneLookup._ID); 482e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 483e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + PhoneLookup.DISPLAY_NAME); 484e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 485e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 486e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 487e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 488e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " + PhoneLookup.TIMES_CONTACTED); 489e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 490e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_STARRED + " AS " + PhoneLookup.STARRED); 491e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 492e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 493e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 494e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.PHOTO_ID + " AS " + PhoneLookup.PHOTO_ID); 495e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 496e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " + PhoneLookup.CUSTOM_RINGTONE); 497e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 498e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.HAS_PHONE_NUMBER + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 499e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 500e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 501e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 502e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 503e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 504e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 505e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 506e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 507e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 5089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 509e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov HashMap<String, String> columns; 5107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 511ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 512ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 513ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups._ID, "groups._id AS _id"); 514035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 515035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 5169261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 5179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 5189261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 51967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.RES_PACKAGE, PackagesColumns.PACKAGE + " AS " + Groups.RES_PACKAGE); 520ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 52167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 522ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 5233cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 52494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 5253cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 52638446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 5273cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYNC1, Tables.GROUPS + "." + Groups.SYNC1 + " AS " + Groups.SYNC1); 5283cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYNC2, Tables.GROUPS + "." + Groups.SYNC2 + " AS " + Groups.SYNC2); 5293cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYNC3, Tables.GROUPS + "." + Groups.SYNC3 + " AS " + Groups.SYNC3); 5303cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYNC4, Tables.GROUPS + "." + Groups.SYNC4 + " AS " + Groups.SYNC4); 531ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 532ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5336cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 534ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 535ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 536d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 537d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 538ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 539ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 540ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 541d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 542d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 543ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 544f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 545ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 546ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 547b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 548b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 549b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 550b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 551d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(AggregationExceptions.CONTACT_ID, 552d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "raw_contacts1." + RawContacts.CONTACT_ID 553d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " AS " + AggregationExceptions.CONTACT_ID); 5545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID, AggregationExceptionColumns.RAW_CONTACT_ID2); 555b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 556b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 557eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 558eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 559eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 560eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 561eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 562eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 56368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 56468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 56568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 56668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 56768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 568e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 56968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 57068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 57168936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 572eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 573eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 574373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 575373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence._ID, Presence._ID); 5764dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 577373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.DATA_ID, Presence.DATA_ID); 578373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_ACCOUNT, Presence.IM_ACCOUNT); 579373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_HANDLE, Presence.IM_HANDLE); 5804dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(Presence.PROTOCOL, Presence.PROTOCOL); 5814dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(Presence.CUSTOM_PROTOCOL, Presence.CUSTOM_PROTOCOL); 582373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.PRESENCE_STATUS, Presence.PRESENCE_STATUS); 583373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.PRESENCE_CUSTOM_STATUS, Presence.PRESENCE_CUSTOM_STATUS); 584373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov sPresenceProjectionMap = columns; 585373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov 586a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap = new HashMap<String, String>(); 587a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap.putAll(sDataProjectionMap); 588a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap.put(Presence.PRESENCE_STATUS, 589e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov Presence.PRESENCE_STATUS); 590a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap.put(Presence.PRESENCE_CUSTOM_STATUS, 591e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov Presence.PRESENCE_CUSTOM_STATUS); 59219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 5931b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 5941b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 5951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 5961b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 5971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 5981b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 5991b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 6001b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 6011b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 6021b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 6031b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 6041b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 6054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsInGroupSelect = Contacts._ID + " IN " 6064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 6074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 6084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 6094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 6104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 6114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 6124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 6134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 6144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " FROM " + Tables.GROUPS 6154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 6164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 6174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 6183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 6193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 6203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 6213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 6223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 624653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 6253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 6273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 6283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 630653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 631653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 632653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mMimetypeId = mOpenHelper.getMimeTypeId(mMimetype); 633653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 634653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 635653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 636653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 6373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 6383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 6393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 6405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 641e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 642e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 643e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 644e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 645653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 646e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 647e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 648e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 6493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 6523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 6533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 6543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 655653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 656653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean markRawContactAsDirty) { 65714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 65814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 659653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 660653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 661653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 662653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 663653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 664653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 665653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 666653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 667653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 668653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 669653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 670653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 671653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 672653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 673653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 674653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 675653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 676653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " = " + dataId, null); 677653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 678653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 679653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (markRawContactAsDirty) { 680653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 681653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 6823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 68514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 68614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 68714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 6883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 6893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 6905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 6913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 6933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 6965ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long newPrimaryId = findNewPrimaryDataId(db, rawContactId); 6973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (newPrimaryId != -1) { 69814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov setIsPrimary(rawContactId, newPrimaryId, getMimeTypeId()); 6993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected long findNewPrimaryDataId(SQLiteDatabase db, long rawContactId) { 703e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 704e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 7055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Cursor c = queryData(db, rawContactId); 7063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 707e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 70814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 70914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA2); 710e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 711e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 712e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 713e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 7143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 7163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 7173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 718e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return primaryId; 719e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 720e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 721e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 722e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 723e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 724e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 725e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 726e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 7273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected Cursor queryData(SQLiteDatabase db, long rawContactId) { 73014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return db.query(DataDeleteQuery.TABLE, DataDeleteQuery.CONCRETE_COLUMNS, 73114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId + 73214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " AND " + MimetypesColumns.MIMETYPE + "='" + mMimetype + "'", 7333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov null, null, null, null); 7343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected void fixContactDisplayName(SQLiteDatabase db, long rawContactId) { 7373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String bestDisplayName = null; 73867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Cursor c = db.query(DisplayNameQuery.TABLE, DisplayNameQuery.COLUMNS, 7395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId, null, null, null, null); 7403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 7413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int maxPriority = -1; 7423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov while (c.moveToNext()) { 7433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String mimeType = c.getString(DisplayNameQuery.MIMETYPE); 7443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov boolean primary; 7453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String name; 7463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) { 7483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov name = c.getString(DisplayNameQuery.DISPLAY_NAME); 7493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov primary = true; 7503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 7513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov name = c.getString(DisplayNameQuery.DATA2); 7523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov primary = (c.getInt(DisplayNameQuery.IS_PRIMARY) != 0); 7533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (primary && name != null) { 7563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Integer priority = sDisplayNamePriorities.get(mimeType); 7573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (priority != null && priority > maxPriority) { 7583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov maxPriority = priority; 7593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov bestDisplayName = name; 7603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 7653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 7663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 768653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setDisplayName(rawContactId, bestDisplayName); 76914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 77014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov // TODO also fix the aggregate contact display name right away 7713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 772a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 773a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 774a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return true; 775a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 7763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 7793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 7813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 7823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 7863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final NameSplitter mNameSplitter; 7883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public StructuredNameRowHandler(NameSplitter nameSplitter) { 7903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 7913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mNameSplitter = nameSplitter; 7923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 7955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 7963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fixStructuredNameComponents(values); 79714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 79814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 79914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 80014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String givenName = values.getAsString(StructuredName.GIVEN_NAME); 80114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String familyName = values.getAsString(StructuredName.FAMILY_NAME); 80214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.insertNameLookupForStructuredName(rawContactId, dataId, givenName, 80314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov familyName); 80414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 80514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 80614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 80714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 80814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 80914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 81014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean markRawContactAsDirty) { 811cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 812cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov fixStructuredNameComponents(values); 813cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 81414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 81514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 81614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 81714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super.update(db, values, c, markRawContactAsDirty); 81814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 81914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean hasGivenName = values.containsKey(StructuredName.GIVEN_NAME); 82014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean hasFamilyName = values.containsKey(StructuredName.FAMILY_NAME); 82114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov if (hasGivenName || hasFamilyName) { 82214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String givenName; 82314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String familyName;// = values.getAsString(StructuredName.FAMILY_NAME); 82414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov if (hasGivenName) { 82514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov givenName = values.getAsString(StructuredName.GIVEN_NAME); 82614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } else { 82714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 82814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov // TODO compiled statement 82914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov givenName = DatabaseUtils.stringForQuery(db, 83014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov "SELECT " + StructuredName.GIVEN_NAME + 83114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " FROM " + Tables.DATA + 83214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " WHERE " + Data._ID + "=" + dataId, null); 83314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 83414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov if (hasFamilyName) { 83514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov familyName = values.getAsString(StructuredName.FAMILY_NAME); 83614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } else { 83714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 83814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov // TODO compiled statement 83914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov familyName = DatabaseUtils.stringForQuery(db, 84014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov "SELECT " + StructuredName.FAMILY_NAME + 84114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " FROM " + Tables.DATA + 84214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " WHERE " + Data._ID + "=" + dataId, null); 84314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 84414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 84514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.deleteNameLookup(dataId); 84614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.insertNameLookupForStructuredName(rawContactId, dataId, givenName, 84714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov familyName); 84814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 84914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 85014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 85114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 85214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 85314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 85414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 85514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 85614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 85714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 85814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 85914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.deleteNameLookup(dataId); 86014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 86114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 8623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Parses the supplied display name, but only if the incoming values do not already contain 8663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * structured name parts. Also, if the display name is not provided, generate one by 8673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * concatenating first name and last name 8683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * 8693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * TODO see if the order of first and last names needs to be conditionally reversed for 8703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * some locales, e.g. China. 8713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private void fixStructuredNameComponents(ContentValues values) { 8733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String fullName = values.getAsString(StructuredName.DISPLAY_NAME); 8743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (!TextUtils.isEmpty(fullName) 8753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.PREFIX)) 8763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.GIVEN_NAME)) 8773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.MIDDLE_NAME)) 8783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.FAMILY_NAME)) 8793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.SUFFIX))) { 8803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 8813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mNameSplitter.split(name, fullName); 8823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.PREFIX, name.getPrefix()); 8843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.GIVEN_NAME, name.getGivenNames()); 8853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.MIDDLE_NAME, name.getMiddleName()); 8863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.FAMILY_NAME, name.getFamilyName()); 8873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.SUFFIX, name.getSuffix()); 8883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (TextUtils.isEmpty(fullName)) { 8913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String givenName = values.getAsString(StructuredName.GIVEN_NAME); 8923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String familyName = values.getAsString(StructuredName.FAMILY_NAME); 8933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (TextUtils.isEmpty(givenName)) { 8943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fullName = familyName; 8953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else if (TextUtils.isEmpty(familyName)) { 8963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fullName = givenName; 8973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 8983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fullName = givenName + " " + familyName; 8993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (!TextUtils.isEmpty(fullName)) { 9023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.DISPLAY_NAME, fullName); 9033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 9093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 9113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 9123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 9143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 9153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 9163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 9173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 9205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 9213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int type; 9223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String label; 9233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (values.containsKey(mTypeColumn)) { 9243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov type = values.getAsInteger(mTypeColumn); 9253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 9263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov type = BaseTypes.TYPE_CUSTOM; 9273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (values.containsKey(mLabelColumn)) { 9293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov label = values.getAsString(mLabelColumn); 9303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 9313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov label = null; 9323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (type != BaseTypes.TYPE_CUSTOM && label != null) { 9357a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException(mLabelColumn + " value can only be specified with " 9363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov + mTypeColumn + "=" + BaseTypes.TYPE_CUSTOM + "(custom)"); 9373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (type == BaseTypes.TYPE_CUSTOM && label == null) { 9407a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException(mLabelColumn + " value must be specified when " 9413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov + mTypeColumn + "=" + BaseTypes.TYPE_CUSTOM + "(custom)"); 9423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return super.insert(db, rawContactId, values); 9453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 9493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 9513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 9523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 9555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 9565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long id = super.insert(db, rawContactId, values); 9575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 9583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return id; 9593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 96214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 96314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean markRawContactAsDirty) { 96414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 96514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 96614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super.update(db, values, c, markRawContactAsDirty); 96714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 96814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 96914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 97014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 97114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 97214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 97314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 97414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 97514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 97614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 97714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 97814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 97914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 98014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 9813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 9823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 9833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 9843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 9853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 9863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 9873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 989a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 990a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 991a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 992a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 993a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 9943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 996e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 997e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 998e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 999e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1000e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1001e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1002e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 10035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 100414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 100514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 100614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 100714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 10085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 100914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.insertNameLookupForEmail(rawContactId, dataId, address); 101014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 101114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 101214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 101314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 101414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 101514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean markRawContactAsDirty) { 101614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 101714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 101814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 101914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 102014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super.update(db, values, c, markRawContactAsDirty); 102114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 102214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.deleteNameLookup(dataId); 102314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.insertNameLookupForEmail(rawContactId, dataId, address); 102414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 102514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 102614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 102714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 102814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 102914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 103014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 103114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 103214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 103314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 103414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.deleteNameLookup(dataId); 103514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 103614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1037e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1038e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1039e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1040e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1041e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1042e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1043e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1044e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1045e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1046e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1047e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1048e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1049e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1050e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 105114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 105214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 105314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 105414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 105514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 105614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 105714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 105814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 105914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 106014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 106114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 106214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 106314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 106414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.insertNameLookupForNickname(rawContactId, dataId, nickname); 106514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 106614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 106714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 106814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 106914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 107014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean markRawContactAsDirty) { 107114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 107214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 107314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 107414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 107514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super.update(db, values, c, markRawContactAsDirty); 107614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 107714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.deleteNameLookup(dataId); 107814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.insertNameLookupForNickname(rawContactId, dataId, nickname); 107914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 108014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 108114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 108214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 108314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 108414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 108514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 108614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 108714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 108814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 108914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mOpenHelper.deleteNameLookup(dataId); 109014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 109114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 109214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 109314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 109414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 10953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 10963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 10983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 10993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 11030b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 11040b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 11050b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 11060b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1107653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 11080b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1109653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 11100b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 11110b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 11120b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 11130b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 11140b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1115653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1116653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1117653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1118653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1119653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1120653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean markRawContactAsDirty) { 112114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 112214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 11230b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 11240b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 11250b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1126653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 11270b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov super.update(db, values, c, markRawContactAsDirty); 1128653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 11290b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 11300b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 11310b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 11320b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov super.update(db, values, c, markRawContactAsDirty); 11330b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 113414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 113514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 113614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 113714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 113814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 113914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 114014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 114114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 114214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 114314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 114414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov fixContactDisplayName(db, rawContactId); 114514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1146653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1147653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1148653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1149e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1150e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1151e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1152e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1153653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1154653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1155653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1156e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1157653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1158653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1159e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1160653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 11615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1162653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1163e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 1164653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1165653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1166653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=" + dataId, null); 1167e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 11683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 11723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 11733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 11743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 11753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 11763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 11773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 11783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 11793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 11803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 11813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 11823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1186653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1187653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1188653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1189653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1190653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1191653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1192653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1193653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1194653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 1195653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return super.insert(db, rawContactId, values); 1196653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1197653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1198653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1199653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1200653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean markRawContactAsDirty) { 120114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1202653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1203653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super.update(db, values, c, markRawContactAsDirty); 1204653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1205653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1206653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1207653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1208653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1209653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1210653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1211653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1212653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1213653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1214653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1215653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1216653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1217653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1218653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1219653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1220653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1221653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1222653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1223653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1224653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1225653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1226653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1227653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1228653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId); 1229653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1230653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1231653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1232653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1233a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1234a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1235a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1236a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1237a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1238653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1239653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1240a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1241a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1242a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1243a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1244a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1245a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1246a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1247a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1248a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1249a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 1250a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1251a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1252a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1253a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1254a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1255a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov boolean markRawContactAsDirty) { 1256a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1257a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super.update(db, values, c, markRawContactAsDirty); 1258a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1259a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1260a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1261a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1262a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1263a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1264a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1265a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1266a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1267a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1268a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1269a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1270a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1271a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1272a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1273a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1274a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1275a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 12763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 127753056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 12784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private OpenHelper mOpenHelper; 127931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1280a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov private ContactAggregator mContactAggregator; 12814097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1282f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1283a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1284a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 128520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 128620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1287ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 128873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private boolean mImportMode; 128973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1290de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov private boolean mScheduleAggregation; 1291de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 1292a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 129353056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 1294a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1295a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1296a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1297a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 1298a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 129953056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 130053056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 1301a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 13024f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 13034f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 13044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1305de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 130635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1307de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1308de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mOpenHelper = (OpenHelper)getOpenHelper(); 1309a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1310a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mOpenHelper, this, mGlobalSearchSupport); 1311cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov mContactAggregator = new ContactAggregator(this, mOpenHelper, mAggregationScheduler); 1312a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1313d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 1314653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1315c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1316653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1317653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1318653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1319653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1320653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1321c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1322653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1323653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1324653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1325653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1326653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1327653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1328653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1329653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1330653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1331653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1332653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 13335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mLastTimeContactedUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 13346cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.TIMES_CONTACTED + "=" + RawContacts.TIMES_CONTACTED + "+1," 1335d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + RawContacts.LAST_TIME_CONTACTED + "=? WHERE " + RawContacts.CONTACT_ID + "=?"); 1336a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 13375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mContactDisplayNameUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 13386cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContactsColumns.DISPLAY_NAME + "=? WHERE " + RawContacts._ID + "=?"); 13393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 134073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 134173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + RawContacts.DIRTY + "=1 WHERE " + RawContacts._ID + "=?"); 134273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1343e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceReplace = db.compileStatement( 1344e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.AGGREGATED_PRESENCE + "(" 1345e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + AggregatedPresenceColumns.CONTACT_ID + ", " 1346e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + Presence.PRESENCE_STATUS 1347e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + ") VALUES (?, (SELECT MAX(" + Presence.PRESENCE_STATUS + ")" 1348e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " FROM " + Tables.PRESENCE + "," + Tables.RAW_CONTACTS 1349a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov + " WHERE " + PresenceColumns.RAW_CONTACT_ID + "=" 1350e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID 1351e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=?))"); 1352e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1353e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceStatusUpdate = db.compileStatement( 1354e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov "UPDATE " + Tables.AGGREGATED_PRESENCE 1355e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " SET " + Presence.PRESENCE_CUSTOM_STATUS + "=? " 1356e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " WHERE " + AggregatedPresenceColumns.CONTACT_ID + "=?"); 1357e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 135828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 135928f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 136028f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 136128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 136228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_conjunctions)); 13634097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 13643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 13653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1366e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 13673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 13683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 136967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 137067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 13713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 13723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 137314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 13743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 13753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1376a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1377a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 13783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13793d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1380568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 13813d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1382568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 13831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 13844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 13854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 138631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1387de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 138831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov protected OpenHelper getOpenHelper(final Context context) { 138931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov return OpenHelper.getInstance(context); 139031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 139131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1392013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1393013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1394013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1395013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 13963d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 13973d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 13983d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 13993d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 14003d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1401568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1402568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1403568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1404568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1405568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1406568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1407568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1408568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1409568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1410ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1411568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1412568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1413568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1414568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1415568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1416568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1417568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1418568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1419568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1420568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1421ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1422ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1423568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov scheduleContactAggregation(); 1424568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1425568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1426568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1427568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1428568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1429568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1430568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 14313d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1432568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1433568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 14343d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 14353d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 14363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 14373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 14383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 14393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 14403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 14413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 14423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 14433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 14443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1445568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 14463d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 144773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = true; 14483d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 14493d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 14503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(true); 14513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 14523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 14533d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 14543d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 145573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } finally { 145673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = false; 14573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 14583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 14593d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1460a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1461a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 1462a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 1463a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 1464a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1465a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1466a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 1467a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1468a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1469a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1470a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1471a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1472a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1473a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mOpenHelper.wipeData(); 1474a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1475a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1476568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1477568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 1478568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1479568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1480568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1481568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1482568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1483568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 1484ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 1485ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 1486ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 1487ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 1488ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 1489ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1490ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 1491ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 1492ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1493ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1494568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1495568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1496568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1497568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1498568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1499568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1500568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1501568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1502568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1503568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1504568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1505568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1506568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1507568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1508568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1509568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1510568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 1511568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1512568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1513568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1514568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1515568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1516568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1517568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 1518568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1519568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1520568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1521568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 15224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1523de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected void onTransactionComplete() { 1524de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (mScheduleAggregation) { 1525de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mScheduleAggregation = false; 1526568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov scheduleContactAggregation(); 1527de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 1528de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onTransactionComplete(); 15294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 15304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1531cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov @Override 1532cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 1533cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null); 1534cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 1535568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1536568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected void scheduleContactAggregation() { 1537568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov mContactAggregator.schedule(); 1538568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1539568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 15403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 15413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 15423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 15433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 15443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 15453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 15473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1550de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 1551a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 1552a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 155335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1554a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 155535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 1556de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov id = mOpenHelper.getSyncState().insert(mDb, values); 155735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 155835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1559d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1560d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 15616bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 15626bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 15636bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 15645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 1565f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 1566d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov id = insertRawContact(values, account); 1567a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1568a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1569a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 15705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 15715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 157273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov id = insertData(values, shouldMarkRawContactAsDirty(uri)); 1573a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1574a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1575a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1576a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 157773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov id = insertData(values, shouldMarkRawContactAsDirty(uri)); 1578a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1579a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1580a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1581ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1582ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 158373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov id = insertGroup(values, account, shouldMarkGroupAsDirty(uri)); 1584ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1585ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1586ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1587eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 1588e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey id = insertSettings(values); 1589eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 1590eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 1591eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 15921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 15931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey id = insertPresence(values); 15941f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 15951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 15961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1597a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 1598f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 1599a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1600a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 16017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 16027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 16037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 16047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1605de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 1606a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1607a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1608a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1609035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 1610035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 1611035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 1612035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 1613035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 16147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 1615035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 1616035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 16176cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME); 16186cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 1619035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 1620035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 1621035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 1622035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 1623035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1624035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 1625035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1626035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 1627df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_NAME, account.name); 1628df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_TYPE, account.type); 1629035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1630035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 16317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 16327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 16337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 1634d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 16356bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 16366bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 16376bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 16386bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1639d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 1640de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 16416bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 16426bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 16436bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 1644a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 1645a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1646a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1647f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 1648a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1649a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1650d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertRawContact(ContentValues values, Account account) { 16516bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /* 16526bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * The contact record is inserted in the contacts table, but it needs to 16536bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * be processed by the aggregator before it will be returned by the 16546bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * "aggregates" queries. 16556bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1656a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 1657d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov overriddenValues.putNull(RawContacts.CONTACT_ID); 1658f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 16597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 16607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 16617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 16623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 16633d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 16643d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov overriddenValues.put(RawContacts.AGGREGATION_MODE, 16653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DISABLED); 16663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 16673d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1668023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov long rawContactId = 1669023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, overriddenValues); 1670023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 1671023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 1672a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1673a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1674a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1675a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 1676a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1677a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1678a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1679a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 168073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private long insertData(ContentValues values, boolean markRawContactAsDirty) { 1681a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 1682de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 1683de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 168467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 1685de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 168620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1687de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 1688de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 1689de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 1690de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 1691de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 1692de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 1693508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 1694de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 1695de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 1696de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 1697de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 1698de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 16994097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1700de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mOpenHelper.getMimeTypeId(mimeType)); 1701de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 1702a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1703a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 1704a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 1705de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (markRawContactAsDirty) { 1706de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 1707a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1708a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1709a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 1710a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 1711a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1712a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 17134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 17144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 17158e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 17168e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 17178e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 17188e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 17198e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 17208e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov int aggregationMode = mOpenHelper.getAggregationMode(rawContactId); 1721f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 17228e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 17238e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 17248e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 17258e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 1726421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 1727de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mScheduleAggregation = true; 1728f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 17298e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 17308e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 17318e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 17328e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 1733f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 17348e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 17358e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 17368e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 1737f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 17388e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 1739f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 17408e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_IMMEDITATE: { 17418e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 1742421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 17438e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 1744f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 17458e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 1746f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 1747f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 1748f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 1749a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 17505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 17519261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 17529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 17535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 17549261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 17559261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 17569261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 17579261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 17589261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 17595ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId) { 17609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Account account = null; 17616cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts._ID + "=" 17625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId, null, null, null, null); 17639261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 17649261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 176567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountName = c.getString(ContactsQuery.ACCOUNT_NAME); 176667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountType = c.getString(ContactsQuery.ACCOUNT_TYPE); 17679261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 17689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana account = new Account(accountName, accountType); 17699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 17709261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 17719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 17729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 17739261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 17749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 17759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 17769261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "has a sourceid the the contact must be associate with " 17779261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 17789261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 17799261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 17809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 17815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 17826cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 17839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 1784df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 17859261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 17869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 17879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return c.getLong(0); 17889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 17899261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 1790df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 1791df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 17929261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 17939261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 17949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 17959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 17969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 17979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 17989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return groupId; 17999261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 18009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 18019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 18029261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 18039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 18049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 18059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 180620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 180720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 180873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private int deleteData(String selection, String[] selectionArgs, 180973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov boolean markRawContactAsDirty) { 181020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 181120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1812de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 1813de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 181414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 1815de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 1816de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 181714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 181814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 1819a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 1820a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 182188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov if (markRawContactAsDirty) { 182288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 1823a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 1824a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 1825a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 182688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 182720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 182820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 1829de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 183020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 183120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 183220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 183320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 183420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 183588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 183688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 183788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 183820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 1839f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 184088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 184188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 184214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=" + dataId, null, 184314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov null); 1844f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 184520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 184620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 184720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 184820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 184920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 185014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 185120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 185220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 185320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 185420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 185520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 185620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 185720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 185820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 185920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 18607a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 186120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 186220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 186320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1864a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 1865a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 18668e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1867a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 1868a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 1869a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 18708e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 187120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 187220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 187320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 187420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 187520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 187620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 1877ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 1878ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 187973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private long insertGroup(ContentValues values, Account account, boolean markAsDirty) { 1880ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 1881ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 1882ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 1883ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1884ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1885ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 188667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.RES_PACKAGE); 188767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 188867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.put(GroupsColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 188967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 189067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.remove(Groups.RES_PACKAGE); 1891ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 189273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov if (markAsDirty) { 189373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov overriddenValues.put(Groups.DIRTY, 1); 189473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 189573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1896ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey long result = mDb.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 1897ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 1898ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey if (overriddenValues.containsKey(Groups.GROUP_VISIBLE)) { 1899ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey mOpenHelper.updateAllVisible(); 1900ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 1901ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 1902ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 1903ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1904ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1905e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey private long insertSettings(ContentValues values) { 1906e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 1907e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 1908e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mOpenHelper.updateAllVisible(); 1909e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 1910e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 1911e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 1912e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 1913ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 19141f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey * Inserts a presence update. 19151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 191670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public long insertPresence(ContentValues values) { 19171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final String handle = values.getAsString(Presence.IM_HANDLE); 19184dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(handle) || !values.containsKey(Presence.PROTOCOL)) { 19194dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 19204dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 19214dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 19224dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov final long protocol = values.getAsLong(Presence.PROTOCOL); 19234dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 19244dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 19254dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (protocol == Im.PROTOCOL_CUSTOM) { 19264dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov customProtocol = values.getAsString(Presence.CUSTOM_PROTOCOL); 19274dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 19284dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 19294dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 19304dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 19311f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 19321f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 19331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // TODO: generalize to allow other providers to match against email 19344dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 19351f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 193670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov StringBuilder selection = new StringBuilder(); 19371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String[] selectionArgs; 19381f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (matchEmail) { 19394dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append( 19404dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "((" + MimetypesColumns.MIMETYPE + "='" + Im.CONTENT_ITEM_TYPE + "'" 19414dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.PROTOCOL + "=?" 19424dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.DATA + "=?"); 19434dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (customProtocol != null) { 19444dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 19454dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(selection, customProtocol); 19464dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 19474dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append(") OR (" 19484dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + MimetypesColumns.MIMETYPE + "='" + Email.CONTENT_ITEM_TYPE + "'" 19494dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Email.DATA + "=?" 19504dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + "))"); 19514dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selectionArgs = new String[] { String.valueOf(protocol), handle, handle }; 19521f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 19534dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append( 19544dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov MimetypesColumns.MIMETYPE + "='" + Im.CONTENT_ITEM_TYPE + "'" 19554dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.PROTOCOL + "=?" 19564dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.DATA + "=?"); 19574dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (customProtocol != null) { 19584dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 19594dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(selection, customProtocol); 19604dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 19614dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 19624dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selectionArgs = new String[] { String.valueOf(protocol), handle }; 19631f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 19641f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 196570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (values.containsKey(Presence.DATA_ID)) { 196670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.append(" AND " + DataColumns.CONCRETE_ID + "=") 196770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov .append(values.getAsLong(Presence.DATA_ID)); 196870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 196970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 197000ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey selection.append(" AND ").append(getContactsRestrictions()); 197170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 19721f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long dataId = -1; 19735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = -1; 1974e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov long contactId = -1; 197570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 19761f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 19771f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 1978de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 197970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.toString(), selectionArgs, null, null, null); 19801f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 198167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 19825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 1983e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 19841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 19851f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 19861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 19871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 19881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 198931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 199031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 199131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 19921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 19931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 19941f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey values.put(Presence.DATA_ID, dataId); 19954dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov values.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 19961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 19971f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // Insert the presence update 1998de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long presenceId = mDb.replace(Tables.PRESENCE, null, values); 1999e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 2000e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov if (contactId != -1) { 2001e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov if (values.containsKey(Presence.PRESENCE_STATUS)) { 2002e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceReplace.bindLong(1, contactId); 2003e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceReplace.bindLong(2, contactId); 2004e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceReplace.execute(); 2005e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2006e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov String status = values.getAsString(Presence.PRESENCE_CUSTOM_STATUS); 2007e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov if (status != null) { 2008e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceStatusUpdate.bindString(1, status); 2009e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceStatusUpdate.bindLong(2, contactId); 2010e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceStatusUpdate.execute(); 2011e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2012e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 20131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return presenceId; 20141f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 20164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2017de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2018508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2019508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 202035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2021de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mOpenHelper.getSyncState().delete(mDb, selection, selectionArgs); 202235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2023d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2024d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 20256bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 2026d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Remove references to the contact first 20276bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov ContentValues values = new ContentValues(); 2028d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.putNull(RawContacts.CONTACT_ID); 2029de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, values, 2030d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null); 20316bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 2032de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.CONTACTS, BaseColumns._ID + "=" + contactId, null); 20336bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 20346bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 20352971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 20362971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final boolean permanently = 20372971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana readBooleanQueryParameter(uri, RawContacts.DELETE_PERMANENTLY, false); 20382971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 20392971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2040e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 20412971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 20422971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 20432971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 20442971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana numDeletes += deleteRawContact(rawContactId, permanently); 20452971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 20462971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 20472971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 20482971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 20492971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 20502971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 20512971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 20525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 20532971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final boolean permanently = 20542971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana readBooleanQueryParameter(uri, RawContacts.DELETE_PERMANENTLY, false); 20552971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 20562971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return deleteRawContact(rawContactId, permanently); 2057508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2058508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 205920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2060944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2061944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong shouldMarkRawContactAsDirty(uri)); 206220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 206320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2064508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: { 2065508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2066f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov return deleteData(Data._ID + "=" + dataId, null, shouldMarkRawContactAsDirty(uri)); 2067ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2068ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2069ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 20702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana boolean markAsDirty = shouldMarkGroupAsDirty(uri); 20712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final boolean deletePermanently = 20722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana readBooleanQueryParameter(uri, Groups.DELETE_PERMANENTLY, false); 20732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return deleteGroup(ContentUris.parseId(uri), markAsDirty, deletePermanently); 20742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 20752971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 20762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 20772971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana boolean markAsDirty = shouldMarkGroupAsDirty(uri); 20786f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov final boolean permanently = 20792971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana readBooleanQueryParameter(uri, RawContacts.DELETE_PERMANENTLY, false); 20802971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 20812971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2082e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 20832971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 20842971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 20852971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana numDeletes += deleteGroup(c.getLong(0), markAsDirty, permanently); 20862971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 20872971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 20882971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 20892971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 20902971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2091508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2092508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2093eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 2094e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return deleteSettings(selection, selectionArgs); 2095eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2096eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 20971f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 2098eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 20991f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 21001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2101508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey default: 21023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 2103508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 21044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 21054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 21062971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana private boolean readBooleanQueryParameter(Uri uri, String name, boolean defaultValue) { 21072971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final String flag = uri.getQueryParameter(name); 21082971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return flag == null 21092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana ? defaultValue 21102971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana : (!"false".equals(flag.toLowerCase()) && !"0".equals(flag.toLowerCase())); 211194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 211294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 211373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private int deleteGroup(long groupId, boolean markAsDirty, boolean permanently) { 211494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana final long groupMembershipMimetypeId = mOpenHelper 211594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2116de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 211794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 211894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 211994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 212094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 212194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana if (permanently) { 2122de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 212394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 212494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 212594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 212673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov if (markAsDirty) { 212773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 212873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 2129de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 213094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 213194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 213294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mOpenHelper.updateAllVisible(); 213394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 213494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 213594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2136e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey private int deleteSettings(String selection, String[] selectionArgs) { 2137e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 2138e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey if (count > 0) { 2139e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mOpenHelper.updateAllVisible(); 2140e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2141e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2142e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2143e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 21445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public int deleteRawContact(long rawContactId, boolean permanently) { 2145c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // TODO delete aggregation exceptions 2146c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mOpenHelper.removeContactIfSingleton(rawContactId); 214733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov if (permanently) { 214814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2149de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 215033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 215111944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov 215211944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov // Clear out data used for aggregation - this deleted contact should not be aggregated 215311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov mDb.execSQL("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 215411944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "=" + rawContactId); 215511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov 215633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov mValues.clear(); 215794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(RawContacts.DELETED, 1); 2158c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2159c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 216073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 21615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return updateRawContact(rawContactId, mValues, null, null); 216233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 216333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 216433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 2165f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana private static Account readAccountFromQueryParams(Uri uri) { 21666cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String name = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 21676cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String type = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 2168f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 2169f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana return null; 2170f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana } 2171f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana return new Account(name, type); 2172f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana } 2173f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana 21744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2175de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2176de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 217735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 217800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 217900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 218000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 218135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2182de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mOpenHelper.getSyncState().update(mDb, values, selection, selectionArgs); 218335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2184d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // TODO(emillar): We will want to disallow editing the contacts table at some point. 2185d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2186944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = mDb.update(Tables.CONTACTS, values, 2187944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs); 218800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 218900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 219000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2191d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2192de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateContactData(ContentUris.parseId(uri), values); 2193c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2194c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2195c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 219620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2197944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2198944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong selectionArgs, shouldMarkRawContactAsDirty(uri)); 219920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 220020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2201c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 220220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA_ID: { 220373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov count = updateData(uri, values, selection, selectionArgs, 220473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov shouldMarkRawContactAsDirty(uri)); 220500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 220600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 22077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 22085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 220973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov // TODO: security checks 2210e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong count = mDb.update(Tables.RAW_CONTACTS, values, 2211e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs); 22127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 22137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 22147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 22155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 221633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 221733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov count = updateRawContact(rawContactId, values, selection, selectionArgs); 22187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 22197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 22207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2221ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2222e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong count = updateGroups(values, appendAccountToSelection(uri, selection), 2223e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionArgs, shouldMarkGroupAsDirty(uri)); 2224ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2225ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2226ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2227ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2228ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 222973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String selectionWithId = (Groups._ID + "=" + groupId + " ") 223073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 2231de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateGroups(values, selectionWithId, selectionArgs, 223273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov shouldMarkGroupAsDirty(uri)); 2233ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2234ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2235ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2236127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 2237de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 2238b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2239b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2240b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2241eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 2242e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey count = updateSettings(values, selection, selectionArgs); 2243eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2244eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2245eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 22467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 2247f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 224800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 224900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 225000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 22514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2253de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov private int updateGroups(ContentValues values, String selectionWithId, 225473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String[] selectionArgs, boolean markAsDirty) { 225573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 225673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 225773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov if (markAsDirty) { 225873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 225973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 226073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 226173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 226273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 226373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 226473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 226573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2266ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 226794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 226894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana // If changing visibility, then update contacts 2269ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 227094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mOpenHelper.updateAllVisible(); 227194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 227294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 227394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 227494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2275e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey private int updateSettings(ContentValues values, String selection, String[] selectionArgs) { 2276e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 2277e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 2278e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mOpenHelper.updateAllVisible(); 2279e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2280e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2281e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2282e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 22835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values, String selection, 228433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov String[] selectionArgs) { 228573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 228673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov // TODO: security checks 22875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov String selectionWithId = (RawContacts._ID + " = " + rawContactId + " ") 228833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov + (selection == null ? "" : " AND " + selection); 22895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = mDb.update(Tables.RAW_CONTACTS, values, selectionWithId, selectionArgs); 22905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 22915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (values.containsKey(RawContacts.ACCOUNT_TYPE) 22925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov || values.containsKey(RawContacts.ACCOUNT_NAME) 22935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov || values.containsKey(RawContacts.SOURCE_ID)) { 22945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov triggerAggregation(rawContactId); 22955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 22965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 22975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 229833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 229933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 2300321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 230173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String[] selectionArgs, boolean markRawContactAsDirty) { 230220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 230320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 230420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 23055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 230620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 230720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 230820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 230920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 231020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 231120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 231220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 231320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 231470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 231570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 231620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 231720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 231820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 231970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 232020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 232170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 232220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 232370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 232420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 232570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 232620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 232720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2328653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 232920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2330653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2331653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 233214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 2333653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 2334653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 2335653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov count += updateData(mValues, c, markRawContactAsDirty); 233620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2337653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 2338653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 233920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 234020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2341653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 234220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 234320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2344653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private int updateData(ContentValues values, Cursor c, boolean markRawContactAsDirty) { 2345653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 2346653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 2347321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2348653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 234914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 2350a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2351a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov rowHandler.update(mDb, values, c, markRawContactAsDirty); 23528e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 2353a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2354a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2355a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 23568e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2357653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 2358321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2359321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 2360de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov private int updateContactData(long contactId, ContentValues values) { 2361d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2362d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // First update all constituent contacts 2363f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov ContentValues optionValues = new ContentValues(5); 23646cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyStringValue(optionValues, RawContacts.CUSTOM_RINGTONE, 2365d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 23666cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.SEND_TO_VOICEMAIL, 2367d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 23686cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.LAST_TIME_CONTACTED, 2369d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 23706cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.TIMES_CONTACTED, 2371d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 23726cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.STARRED, 2373d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 2374d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2375d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 2376d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (optionValues.size() == 0) { 2377d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 2378d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2379d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2380c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey if (optionValues.containsKey(RawContacts.STARRED)) { 2381c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 2382c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey optionValues.put(RawContacts.DIRTY, 1); 2383c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 2384c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 2385de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, optionValues, 2386d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null); 2387de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.CONTACTS, values, Contacts._ID + "=" + contactId, null); 2388f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2389d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2390d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public void updateContactTime(long contactId, long lastTimeContacted) { 2391f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 2392d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(2, contactId); 2393f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.execute(); 2394d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2395d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 23965ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static class RawContactPair { 23975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov final long rawContactId1; 23985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov final long rawContactId2; 2399127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2400127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov /** 24015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Constructor that ensures that this.rawContactId1 < this.rawContactId2 2402127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov */ 24035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public RawContactPair(long rawContactId1, long rawContactId2) { 24045ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (rawContactId1 < rawContactId2) { 24055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId1 = rawContactId1; 24065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId2 = rawContactId2; 2407127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } else { 24085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId2 = rawContactId1; 24095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId1 = rawContactId2; 2410127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2411127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2412127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 241380c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 2414127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 2415127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 2416d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = values.getAsInteger(AggregationExceptions.CONTACT_ID); 24175ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID); 241880c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 24193cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov // First, we build a list of rawContactID-rawContactID pairs for the given contact. 24205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov ArrayList<RawContactPair> pairs = new ArrayList<RawContactPair>(); 2421d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts.CONTACT_ID 2422d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + "=" + contactId, null, null, null, null); 2423127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov try { 2424127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov while (c.moveToNext()) { 24255ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long aggregatedContactId = c.getLong(ContactsQuery.RAW_CONTACT_ID); 24265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (aggregatedContactId != rawContactId) { 24275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov pairs.add(new RawContactPair(aggregatedContactId, rawContactId)); 2428e2e0ba75ce239f0f5481cdef9082daebf8fc2d35Dmitri Plotnikov } 2429b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2430b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } finally { 2431b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov c.close(); 2432b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2433127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2434127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // Now we iterate through all contact pairs to see if we need to insert/delete/update 2435127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // the corresponding exception 2436127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 2437127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 24385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov for (RawContactPair pair : pairs) { 2439127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov final String whereClause = 24405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov AggregationExceptionColumns.RAW_CONTACT_ID1 + "=" + pair.rawContactId1 + " AND " 24415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + AggregationExceptionColumns.RAW_CONTACT_ID2 + "=" + pair.rawContactId2; 2442127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 2443127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, whereClause, null); 2444127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } else { 24455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov exceptionValues.put(AggregationExceptionColumns.RAW_CONTACT_ID1, pair.rawContactId1); 24465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov exceptionValues.put(AggregationExceptionColumns.RAW_CONTACT_ID2, pair.rawContactId2); 2447127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 2448127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov exceptionValues); 2449127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2450127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2451127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2452421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 24538e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId, 24548e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mOpenHelper.getContactId(rawContactId)); 24558e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC 24568e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov || exceptionType == AggregationExceptions.TYPE_KEEP_OUT) { 24578e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 24587a39bf269294a8130ddd463460b9b36cf4ff74a8Dmitri Plotnikov } 2459127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2460127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 2461127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 2462127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 2463b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2464b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2465619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2466619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 2467619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Test if a {@link String} value appears in the given list, and add to the 2468619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * array if the value doesn't already appear. 2469619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 2470619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private String[] assertContained(String[] array, String value) { 2471ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (array != null && !mOpenHelper.isInProjection(array, value)) { 2472619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey String[] newArray = new String[array.length + 1]; 2473619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey System.arraycopy(array, 0, newArray, 0, array.length); 2474619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey newArray[array.length] = value; 2475619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey array = newArray; 2476619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2477619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return array; 2478619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2479619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 24804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 24814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 24824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 24830b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 24844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 248535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2486d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 24871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 2488c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 2489c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2490619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 2491619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 2492a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 24934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 249435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 249535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().query(db, projection, selection, selectionArgs, 249635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 249735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2498d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2499ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 2500619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 2501619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2502619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2503d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 25044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2505ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 25064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + contactId); 25076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 25086bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 25096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 25105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 25115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 25125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 25135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 25145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 25155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 25165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 25175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 25185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 25195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 25205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 25215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov setTablesAndProjectionMapForContacts(lookupQb, projection); 25225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=" + contactId + " AND " + 25235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.LOOKUP_KEY + "="); 25245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhereEscapeString(lookupKey); 25255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, selectionArgs, sortOrder, 25265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 25275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 25285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 25295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 25305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 25315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 25325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 25335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 25345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 25355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 25365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 25375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 25385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 2539ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 2540ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 2541ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 25424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 25434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 2544e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 2545e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov appendContactByFilterAsNestedQuery(sb, filterParam); 25464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sb.toString()); 2547ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2548ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2549ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2550ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 2551ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 2552ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 25534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 2554ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 2555d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 25564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 25574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 2558e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 2559e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov appendContactByFilterAsNestedQuery(sb, filterParam); 25604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 25614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 25624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 2563ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 2564ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 25654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 25664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 25674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 2568d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2569d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final String starredQuery = qb.buildQuery(projection, Contacts.STARRED + "=1", 25704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 2571d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2572d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 2573d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 2574ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 25754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 25764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 2577d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2578d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String frequentQuery = qb.buildQuery(projection, 2579d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 2580d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 25814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 2582d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2583d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 2584d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 2585d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 25864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 25874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 2588d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 2589d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 2590d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2591d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 2592d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2593d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2594ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 2595ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 2596b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 25974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sContactsInGroupSelect); 25984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 2599b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 2600b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 2601b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 2602b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 2603d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 26044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 26054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 26064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 26074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 26084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov appendAccountFromParameter(qb, uri); 26094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 26106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 26116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 261200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2613ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 26143653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 26153653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 26163653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 26173653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 26183653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov appendAccountFromParameter(qb, uri); 26193653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 26203653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 26213653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 26223653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 26233653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 26244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 26254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 26264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 26274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 26282815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 26292815f58f72f109790585931f601a63ddc02536a5Evan Millar } 26302815f58f72f109790585931f601a63ddc02536a5Evan Millar 2631ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 26324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 26334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 2634ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 2635ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 26364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 26374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 26384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 26394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 26404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + sb); 2641ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2642ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2643ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2644ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 26454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 26464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 26474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 26484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 26494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 26504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 26514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 26524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS_FILTER: { 26534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 26544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 26554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 26564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 26574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + CommonDataKinds.Email.DATA + "="); 26584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhereEscapeString(uri.getLastPathSegment()); 26594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 2660ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2661ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2662ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 2663ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 26644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 26654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 26664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Data.MIMETYPE + " = '" + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 2667ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2668ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2669ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 26705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 26714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getRawContactView()); 2672d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 26734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 26744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 26754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 26765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 26775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 26784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getRawContactView()); 2679d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 26804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts._ID + "=" + rawContactId); 26814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 26824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 26834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 26845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 26855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 26864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 26874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 26884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Data.RAW_CONTACT_ID + "=" + rawContactId); 2689e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 2690e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 2691e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 2692e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 26934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 26944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 26954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov appendAccountFromParameter(qb, uri); 2696e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 2697e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 2698e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 26994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 27004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 27014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 27024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Data._ID + "=" + ContentUris.parseId(uri)); 27034f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 27044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2706a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov case DATA_WITH_PRESENCE: { 2707a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov qb.setTables(mOpenHelper.getDataView() + " data" 2708e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE 2709e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " ON (" + AggregatedPresenceColumns.CONTACT_ID + "=" 2710e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 2711a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov qb.setProjectionMap(sDataWithPresenceProjectionMap); 2712a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 2713a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 2714a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 2715a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 27164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 2717a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 2718a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 2719a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 2720e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 2721a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2722a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2723e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 2724e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov mOpenHelper.buildPhoneLookupAndContactQuery(qb, number); 2725e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 2726e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 2727e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 2728e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 2729e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 2730a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2731a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2732a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2733ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2734ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 2735ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 2736ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2737ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2738ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2739ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2740ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 2741ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 2742ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 2743ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(GroupsColumns.CONCRETE_ID + "=" + groupId); 2744ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2745ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2746ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2747ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 274899a9b5ec879f6cd6876f7f6b680b82d8304e6b92Dmitri Plotnikov qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 2749ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 2750ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey groupBy = GroupsColumns.CONCRETE_ID; 2751ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2752ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2753ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2754b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 27555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS_JOIN_RAW_CONTACTS); 2756b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 2757b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2758b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2759b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 276031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 2761d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 276231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 2763d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 2764d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 276531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 276631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 276731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 276831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 2769d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(contactId, projection, 2770d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sContactsProjectionMap, maxSuggestions); 277131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 277231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 2773eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 2774eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 2775eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 2776e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2777e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 2778e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 2779e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final String groupMembershipMimetypeId = Long.toString(mOpenHelper 2780e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 2781ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (mOpenHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 2782e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 2783e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2784ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (mOpenHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 2785e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 2786e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2787e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2788eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2789eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2790eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 27915ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case PRESENCE: { 2792373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setTables(Tables.PRESENCE); 2793373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setProjectionMap(sPresenceProjectionMap); 27945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 27955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 27965ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 27975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case PRESENCE_ID: { 2798373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setTables(Tables.PRESENCE); 2799373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setProjectionMap(sPresenceProjectionMap); 2800373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.appendWhere(Presence._ID + "=" + ContentUris.parseId(uri)); 28015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 28025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 28035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 2804c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 2805a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 2806c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2807c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2808c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 2809b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2810b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh(db, contactId, projection); 2811c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2812c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 28131b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 28141b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 28151b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 28161b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 28171b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 28181b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 28191b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 28201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 28211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 28221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 28231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 28241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 28251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 28261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 28271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 28281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 28291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 28301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 28311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 28321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 28331b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(sContactsInGroupSelect); 28341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 28351b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 28361b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 28374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 2838f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 2839c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 28404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 28414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 28425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 28435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 28445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 28455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 28465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 28475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 2848038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 2849038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 2850038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 2851038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 28525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 28535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 28544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 28554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 28564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 28574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 28584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 28594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 28605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 28615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 28625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 28635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 28645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 28655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 28665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 28675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 28685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 28695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 28705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 28715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 28725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 28735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 28745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 28755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 28765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 28775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 28785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 28795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 28805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 28815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 28825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 28835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 28845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 28855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 28865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 28875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 28885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 28895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 28905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 28915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 28925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 28935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 28945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 28955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 28965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 28975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 28985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 28995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 29005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 29035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 29045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 29055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 29065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 29075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 29085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 29095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 29105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 29135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 29145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 29165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 29175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 29185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 29195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 29205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 29215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 29225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 29235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 29245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 29255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 29265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 29275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 29285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 29295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 29305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 29345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 29355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 29385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 29415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 29425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 29445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 29455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 29465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 29475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 29485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 29495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 29515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 29525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 29535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 29545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 29575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 29585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 29595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 29605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 29615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 29625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 29635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 29675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 29685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 29715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 29725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 29735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 29745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 29755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 29765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 29775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 29785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 29815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 29825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 29835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 29855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 29865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 29875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 29885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 29895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 29905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 29915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 29925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 29935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 29945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 29955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 29965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 29975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 29985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 29995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 30035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 30045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 30065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 30075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 30095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 30105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 30115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 30125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 30135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 30145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 30155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 30165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 30175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 30185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 30195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 30205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 30215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 30225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 30235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 30245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 30255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 30265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 30275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 30285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 30295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 30305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 30315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 30335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 30345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 30385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 30395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 30405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 30415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3044ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, String[] projection) { 3045ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov String contactView = mOpenHelper.getContactView(); 3046ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov boolean needsPresence = mOpenHelper.isInProjection(projection, Contacts.PRESENCE_STATUS, 3047ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.PRESENCE_CUSTOM_STATUS); 3048ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (!needsPresence) { 3049ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setTables(contactView); 3050ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 3051ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } else { 3052ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setTables(contactView + " LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + " ON (" 3053ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ") "); 3054ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setProjectionMap(sContactsWithPresenceProjectionMap); 3055ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 3056ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 3057ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 3058ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 30594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 30604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 30614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 30624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 30634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 30644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 30654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 30664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 30674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 30684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 30694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 30704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 30714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3072e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 3073e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 3074e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 3075e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(accountName)) { 3076e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 3077e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 3078e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 3079e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 3080e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 3081e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 3082e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 3083e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 3084e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3085e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 3086e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 3087e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 3088e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3089e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3090e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 30917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 3092c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 3093c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 3094c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 3095c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 3096c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 3097c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private String getLimit(Uri url) { 3098c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limitParam = url.getQueryParameter("limit"); 3099c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 3100c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3101c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3102c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 3103c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 3104c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 3105c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 3106c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 3107c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3108c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3109c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 3110c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 3111c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 3112c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3113c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3114c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3115c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 311600ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 31174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (mOpenHelper.hasRestrictedAccess()) { 311870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 311970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 31206cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 312170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 312270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 312370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 312470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 31254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (mOpenHelper.hasRestrictedAccess()) { 312670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 312767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 31285ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 31295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 3130619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3131619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3132619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3133b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 3134b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 3135b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 3136b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 3137b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov case CONTACTS_PHOTO: 3138b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 3139b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 3140b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3141b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3142b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 3143b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3144b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 3145b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mOpenHelper.getDataView() + 3146b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 3147b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=" + contactId; 3148b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 3149b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, null); 3150b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3151b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 3152b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("No file at: " + uri); 3153b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3154b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3155b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3156b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3157b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3158619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 31597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 31607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 31617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 31627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static class ContactsEntityIterator implements EntityIterator { 31637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 31647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 31657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 31667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 31677a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 31687a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 31697a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 31707a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 31717a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 31727a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 31737a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 31747a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 31757a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 31767a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 31777a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 31787a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 31797a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 31807a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 31817a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 31827a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 31837a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 31847a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 31857a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4}; 31867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 31877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] PROJECTION = new String[]{ 31886cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 31896cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 31906cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.SOURCE_ID, 31916cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.VERSION, 31926cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.DIRTY, 31937a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data._ID, 31947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RES_PACKAGE, 31957a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.MIMETYPE, 31967a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 31977a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 31987a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 31997a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 32007a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 32017a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 32027a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 32037a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 32047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 32057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 32067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 32077a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 32087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 32097a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 32107a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 32117a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 32127a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 32137a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 32147a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4, 32157a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RAW_CONTACT_ID, 32167a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.IS_PRIMARY, 32177a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA_VERSION, 32187a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana GroupMembership.GROUP_SOURCE_ID, 32197a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC1, 32207a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC2, 32217a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC3, 322294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana RawContacts.SYNC4, 322338446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey RawContacts.DELETED, 3224c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.CONTACT_ID, 3225c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.STARRED}; 3226035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 3227035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 3228035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 3229035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 3230035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 3231035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 3232035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 323367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_RES_PACKAGE = 6; 323467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_MIMETYPE = 7; 323567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA1 = 8; 32367a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_RAW_CONTACT_ID = 27; 32377a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_IS_PRIMARY = 28; 32387a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_DATA_VERSION = 29; 32397a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_GROUP_SOURCE_ID = 30; 32407a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 31; 32417a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 32; 32427a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 33; 32437a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 34; 324494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana private static final int COLUMN_DELETED = 35; 324538446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey private static final int COLUMN_CONTACT_ID = 36; 3246c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey private static final int COLUMN_STARRED = 37; 32477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 32487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public ContactsEntityIterator(ContactsProvider2 provider, String contactsIdString, Uri uri, 32497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 32507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 32517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 32527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final String updatedSortOrder = (sortOrder == null) 32537a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana ? Data.RAW_CONTACT_ID 32547a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana : (Data.RAW_CONTACT_ID + "," + sortOrder); 32557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 32567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 32577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 3258226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setTables(Tables.CONTACT_ENTITIES); 32597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 32605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.appendWhere(Data.RAW_CONTACT_ID + "=" + contactsIdString); 32617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 32626cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 32636cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 3264035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName)) { 32656cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 3266035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 32676cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 3268035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 3269035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 32707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 32717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana null, null, updatedSortOrder); 32727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 32737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 32747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3275038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 3276038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 3277038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 3278038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 3279038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 3280038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 3281038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana 32827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 32837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 32847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 32857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 32867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 32877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 32887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 32897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 32907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 32917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 32927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 32937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 32947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 32957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 32967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 32977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 32987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 32997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 33007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 33017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 33027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 33037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 33047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 33057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 33067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 33077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 33087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final long rawContactId = c.getLong(COLUMN_RAW_CONTACT_ID); 33097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 33107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 33117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 33126cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 33136cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 33145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 33156cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 33166cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 33176cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 33187a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC1, c.getString(COLUMN_SYNC1)); 33197a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC2, c.getString(COLUMN_SYNC2)); 33207a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC3, c.getString(COLUMN_SYNC3)); 33217a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC4, c.getString(COLUMN_SYNC4)); 332294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana contactValues.put(RawContacts.DELETED, c.getLong(COLUMN_DELETED)); 332338446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey contactValues.put(RawContacts.CONTACT_ID, c.getLong(COLUMN_CONTACT_ID)); 3324c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey contactValues.put(RawContacts.STARRED, c.getLong(COLUMN_STARRED)); 33257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 33267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 33277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 33287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 33297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana if (rawContactId != c.getLong(COLUMN_RAW_CONTACT_ID)) { 33307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 33317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 33327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 33337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 33347a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data._ID, c.getString(COLUMN_DATA_ID)); 33357a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 33367a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 33377a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.IS_PRIMARY, c.getString(COLUMN_IS_PRIMARY)); 33387a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 33399261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 33409261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana dataValues.put(GroupMembership.GROUP_SOURCE_ID, 33419261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.getString(COLUMN_GROUP_SOURCE_ID)); 33429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 33437a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 33447a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana for (int i = 0; i < DATA_KEYS.length; i++) { 33457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 33467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 33477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 33487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 33497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 33507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 33517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 33527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 33537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 33547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 33557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 33567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 33577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 33587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 33597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 33607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 33617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 33627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 33637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 33647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 33657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3366226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana /** 3367226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 3368226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 3369226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana */ 3370226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static class GroupsEntityIterator implements EntityIterator { 3371226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private final Cursor mEntityCursor; 3372226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private volatile boolean mIsClosed; 3373226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3374226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final String[] PROJECTION = new String[]{ 3375226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups._ID, 3376226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_NAME, 3377226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_TYPE, 3378226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.SOURCE_ID, 3379226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.DIRTY, 3380226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.VERSION, 3381226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.RES_PACKAGE, 3382226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE, 3383226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE_RES, 33847a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.GROUP_VISIBLE, 33857a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC1, 33867a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC2, 33877a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC3, 33887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC4, 33897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYSTEM_ID, 339094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.NOTES, 339194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.DELETED}; 3392226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3393226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ID = 0; 3394226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_NAME = 1; 3395226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_TYPE = 2; 3396226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_SOURCE_ID = 3; 3397226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_DIRTY = 4; 3398226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_VERSION = 5; 3399226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_RES_PACKAGE = 6; 3400226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE = 7; 3401226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE_RES = 8; 3402226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_GROUP_VISIBLE = 9; 34037a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 10; 34047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 11; 34057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 12; 34067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 13; 34077a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYSTEM_ID = 14; 34087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_NOTES = 15; 340994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana private static final int COLUMN_DELETED = 16; 3410226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3411226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 3412226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 3413226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = false; 3414226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3415226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String updatedSortOrder = (sortOrder == null) 3416226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ? Groups._ID 3417226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana : (Groups._ID + "," + sortOrder); 3418226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3419226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 3420226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 3421226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 3422226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setProjectionMap(sGroupsProjectionMap); 3423226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (groupIdString != null) { 3424226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups._ID + "=" + groupIdString); 3425226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3426226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountName = uri.getQueryParameter(Groups.ACCOUNT_NAME); 3427226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountType = uri.getQueryParameter(Groups.ACCOUNT_TYPE); 3428226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!TextUtils.isEmpty(accountName)) { 3429226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups.ACCOUNT_NAME + "=" 3430226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 3431226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + Groups.ACCOUNT_TYPE + "=" 3432226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 3433226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3434226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 3435226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana null, null, updatedSortOrder); 3436226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToFirst(); 3437226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3438226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3439226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public void close() { 3440226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 3441226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("closing when already closed"); 3442226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3443226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = true; 3444226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.close(); 3445226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3446226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3447226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public boolean hasNext() throws RemoteException { 3448226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 3449226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 3450226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3451226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3452226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return !mEntityCursor.isAfterLast(); 3453226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3454226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3455038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 3456038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 3457038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 3458038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 3459038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 3460038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 3461e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 3462226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public Entity next() throws RemoteException { 3463226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 3464226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 3465226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3466226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!hasNext()) { 3467226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 3468226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3469226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3470226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 3471226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3472226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final long groupId = c.getLong(COLUMN_ID); 3473226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3474226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana // we expect the cursor is already at the row we need to read from 3475226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ContentValues groupValues = new ContentValues(); 3476226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 3477226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 3478226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups._ID, groupId); 3479226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 3480226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 3481226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 3482226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 3483226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 3484226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 3485226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 34867a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC1, c.getString(COLUMN_SYNC1)); 34877a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC2, c.getString(COLUMN_SYNC2)); 34887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC3, c.getString(COLUMN_SYNC3)); 34897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC4, c.getString(COLUMN_SYNC4)); 34907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYSTEM_ID, c.getString(COLUMN_SYSTEM_ID)); 349194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana groupValues.put(Groups.DELETED, c.getLong(COLUMN_DELETED)); 34927a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.NOTES, c.getString(COLUMN_NOTES)); 3493226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Entity group = new Entity(groupValues); 3494226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3495226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToNext(); 3496226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3497226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return group; 3498226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3499226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3500226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3501a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 35027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 35037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 3504568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 3505568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 35067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 35077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 35085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: 35095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: 35107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 35115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (match == RAW_CONTACTS_ID) { 35127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 35137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 35147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 35157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return new ContactsEntityIterator(this, contactsIdString, 35167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana uri, selection, selectionArgs, sortOrder); 3517226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS: 3518226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS_ID: 3519226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String idString = null; 3520226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (match == GROUPS_ID) { 3521226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana idString = uri.getPathSegments().get(1); 3522226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 3523226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 3524226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return new GroupsEntityIterator(this, idString, 3525226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana uri, selection, selectionArgs, sortOrder); 35267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 35277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 35287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 35297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 35307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 35314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 35324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 3533a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 35344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 3535d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: return Contacts.CONTENT_TYPE; 3536d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: return Contacts.CONTENT_ITEM_TYPE; 35375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: return RawContacts.CONTENT_TYPE; 35385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: return RawContacts.CONTENT_ITEM_TYPE; 3539508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 35406bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 3541508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3542b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey return mOpenHelper.getDataMimeType(dataId); 354331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: return AggregationExceptions.CONTENT_TYPE; 354431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_EXCEPTION_ID: return AggregationExceptions.CONTENT_ITEM_TYPE; 3545eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: return Settings.CONTENT_TYPE; 3546d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: return Contacts.CONTENT_TYPE; 3547c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 3548c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 3549c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 3550c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 355161efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 355261efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 35534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 35565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void setDisplayName(long rawContactId, String displayName) { 35573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 35583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mContactDisplayNameUpdate.bindString(1, displayName); 35593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 35603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mContactDisplayNameUpdate.bindNull(1); 35613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 35625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mContactDisplayNameUpdate.bindLong(2, rawContactId); 35633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mContactDisplayNameUpdate.execute(); 35643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 35653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 356673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 356773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Checks the {@link Data#MARK_AS_DIRTY} query parameter. 356873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * 356973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Returns true if the parameter is missing or is either "true" or "1". 357073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 357173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private boolean shouldMarkRawContactAsDirty(Uri uri) { 357273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov if (mImportMode) { 357373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov return false; 357473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 357573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 357673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String param = uri.getQueryParameter(Data.MARK_AS_DIRTY); 357773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov return param == null || (!param.equalsIgnoreCase("false") && !param.equals("0")); 357873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 357973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 358073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 358173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 358273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 358373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 358473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.bindLong(1, rawContactId); 358573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.execute(); 358673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 358773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 358873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 358973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Checks the {@link Groups#MARK_AS_DIRTY} query parameter. 359073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * 359173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Returns true if the parameter is missing or is either "true" or "1". 359273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 359373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private boolean shouldMarkGroupAsDirty(Uri uri) { 359473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov if (mImportMode) { 359573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov return false; 359673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 359773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 35982971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return readBooleanQueryParameter(uri, Groups.MARK_AS_DIRTY, true); 359973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 360073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3601c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 3602c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 3603c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 3604c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 3605c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 3606c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 3607653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 3608c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 3609653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 3610653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 3611c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 3612c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3613c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 3614c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 3615c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 3616c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 3617c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 3618c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 3619c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 3620653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 3621c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 3622653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 3623653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 3624c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 3625c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3626ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3627e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov private void appendContactByFilterAsNestedQuery(StringBuilder sb, String filterParam) { 3628e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append("(SELECT DISTINCT " + RawContacts.CONTACT_ID + " FROM " + Tables.RAW_CONTACTS 3629e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " JOIN name_lookup ON(" + RawContactsColumns.CONCRETE_ID + "=raw_contact_id)" 3630e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " WHERE normalized_name GLOB '"); 3631e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 3632e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append("*')"); 3633e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3634e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 36355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 3636c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 3637c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 3638c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 3639c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3640c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3641a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 3642c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit) { 3643c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append("(SELECT DISTINCT raw_contact_id FROM name_lookup WHERE normalized_name GLOB '"); 3644c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 3645c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append("*'"); 3646c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limit != null) { 3647c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(" LIMIT ").append(limit); 3648c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3649c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(")"); 3650ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3651ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 36524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 36534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 36544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 36554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 3656b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 3657b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 3658b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 3659b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 3660b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 36614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 36624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 3663b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 3664b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3665b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3666caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 3667caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 3668caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 3669caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 3670df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 3671df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 3672caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 3673caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 3674caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 3675caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 36766f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 3677caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 36786f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 3679caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 36804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 3681