ContactsProvider2.java revision d60cf9ba1d039f1a22375f56c18356e0d4f8ca14
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 193de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.internal.content.SyncStateContentProviderHelper; 203de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 213de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.AggregatedPresenceColumns; 223de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.AggregationExceptionColumns; 233de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.Clauses; 243de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.ContactsColumns; 253de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.DataColumns; 263de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.DisplayNameSources; 273de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.GroupsColumns; 283de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.MimetypesColumns; 293de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.NameLookupColumns; 303de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.NameLookupType; 31f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.NicknameLookupColumns; 323de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.PhoneColumns; 333de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.PhoneLookupColumns; 343de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.PresenceColumns; 353de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.RawContactsColumns; 363de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.SettingsColumns; 37a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.StatusUpdatesColumns; 383de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.Tables; 39a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Lists; 40a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Maps; 41a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Sets; 423de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 43b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 44caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 4570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wongimport android.accounts.OnAccountsUpdatedListener; 46c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 47568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 48568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 4935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 5235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.Entity; 5367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.EntityIterator; 54568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 553d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 5667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 573de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.content.SharedPreferences.Editor; 58b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 60ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 61a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 62b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 63b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 66c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 68d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 69b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 700e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 71d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 723d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 73508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 743de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 753de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.LiveFolders; 763de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.OpenableColumns; 773de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.SyncStateContract; 78b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 793de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 803de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 813de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 823de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 833de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Presence; 843de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 853de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 87ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 88ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 92de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 93b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 944097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 9567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 96a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 97a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 98f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Token; 99f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer; 100c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 102d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 103b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 104d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 105d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 106f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport java.lang.ref.SoftReference; 1077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 109b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1100e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 112622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 113b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1140e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 115ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 12170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wongpublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdatedListener { 122caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 123bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 124bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 125bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 127619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 128619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 129619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1333d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1343d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1353d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1410e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1420e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 143a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 145d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 146d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.TIMES_CONTACTED + " DESC, " 1479b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 148d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 149d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 150d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 151d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 152d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 1624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 1664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1676bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1686bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 169ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 17048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 17148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 17248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 17348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 17448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 17548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 17648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 17748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 178a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1796bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1806bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 181b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 182b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 183b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 1841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE = 7000; 1851f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE_ID = 7001; 1861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 18731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 18831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 189eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 190eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 191ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 192ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 193ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 194ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 19535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 196b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 19735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 198c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 199c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 200c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 201a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov private static final int DATA_WITH_PRESENCE = 13000; 20219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 2031b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2041b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2051b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2061b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2071b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 20867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private interface ContactsQuery { 2095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final String TABLE = Tables.RAW_CONTACTS; 2109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 21167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2126cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2136cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 2146cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 215ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 216ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2175ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 21867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_NAME = 1; 21967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_TYPE = 2; 22067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 22167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 222d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 223d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final String TABLE = Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS; 22467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 22567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2266cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 228d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.CONCRETE_ID, 2293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.CONCRETE_ID, 230ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 231ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 232d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 23367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 234d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 23567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int MIMETYPE_ID = 3; 236ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private interface DisplayNameQuery { 23967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final String[] COLUMNS = new String[] { 2423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 244f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 245a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka Organization.TITLE, 2463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 0; 2493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 1; 250a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public static final int DATA = 2; 251a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public static final int TITLE = 3; 2523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 25414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 25567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 25788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 262f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 26388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 26488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 26588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 26688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 26788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 26888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 26988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 270f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 2713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 27314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 277f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 2783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 28014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 281321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 28220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 28320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 284321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 285321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 28620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 28720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 288f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 289f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private interface NicknameLookupQuery { 290f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 291f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 292f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] COLUMNS = new String[] { 293f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.CLUSTER 294f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov }; 295f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 296f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int CLUSTER = 0; 297f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 298f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 29925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private static final HashMap<String, Integer> sDisplayNameSources; 3003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov static { 30125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources = new HashMap<String, Integer>(); 30225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(StructuredName.CONTENT_ITEM_TYPE, 30325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.STRUCTURED_NAME); 304a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sDisplayNameSources.put(Nickname.CONTENT_ITEM_TYPE, 305a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka DisplayNameSources.NICKNAME); 30625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Organization.CONTENT_ITEM_TYPE, 30725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.ORGANIZATION); 30825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Phone.CONTENT_ITEM_TYPE, 30925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.PHONE); 31025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Email.CONTENT_ITEM_TYPE, 31125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.EMAIL); 3123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 31331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 314caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov public static final String DEFAULT_ACCOUNT_TYPE = "com.google.GAIA"; 315df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 316caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 317038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 318038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 319e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 321ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains contacts and presence columns */ 322ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov private static final HashMap<String, String> sContactsWithPresenceProjectionMap; 323ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 324d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 3254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3299261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 330e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 331ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 332ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 333ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 334ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 335373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 336b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 337eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 338eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 339373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains Presence columns */ 340373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov private static final HashMap<String, String> sPresenceProjectionMap; 34119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov /** Contains Presence columns */ 342a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov private static final HashMap<String, String> sDataWithPresenceProjectionMap; 3431b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3441b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 346b67163a1088f09c59f324350662eb18772fac6b6Evan Millar /** Sql where statement for filtering on groups. */ 347d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String sContactsInGroupSelect; 34819a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 349c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 350c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 352c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 353d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Precompiled sql statement for incrementing times contacted for an contact */ 354f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private SQLiteStatement mLastTimeContactedUpdate; 3553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 35625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 35773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** Precompiled sql statement for marking a raw contact as dirty */ 35873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private SQLiteStatement mRawContactDirtyUpdate; 359e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov /** Precompiled sql statement for updating an aggregated presence status */ 360a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 361f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 362f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 363a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 364a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 365a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 366a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 367a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 3684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 3694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 370a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 371d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 372d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 373d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 3743653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 3753653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 3762d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 3772d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 3783653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 3795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 3805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 3815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 3825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 383ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 384ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 3855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 3863653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 3875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 3885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 3895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 390b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 3924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 393ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 39448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 3955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 396ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 3974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 39848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 3995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 402ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 40348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 405ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 406ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 407ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 408ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 40935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 410b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 411b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 41235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 413a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 414b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 415b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 416b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 417b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 419eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 420eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 421bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence", PRESENCE); 422bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence/#", PRESENCE_ID); 4231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 424c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 425c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 426c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 427c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 428c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 429c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 430c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4331b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 4351b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 4361b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 4371b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 4381b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 4391b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 44019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov // Private API 441a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data_with_presence", DATA_WITH_PRESENCE); 44219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 44319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 44419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 445038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 446038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 447e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 4494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 4504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 4514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 457f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 4584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 460d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey sContactsProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 461d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 462d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey sContactsProjectionMap.put(OpenableColumns.SIZE, "0 AS " + OpenableColumns.SIZE); 4634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 464ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap = new HashMap<String, String>(); 465ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap.putAll(sContactsProjectionMap); 466ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap.put(Contacts.PRESENCE_STATUS, 467a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + Presence.PRESENCE_STATUS 468a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " AS " + Contacts.PRESENCE_STATUS); 469ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap.put(Contacts.PRESENCE_CUSTOM_STATUS, 470a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov StatusUpdatesColumns.STATUS 471a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " AS " + Contacts.PRESENCE_CUSTOM_STATUS); 472a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov sContactsWithPresenceProjectionMap.put(Contacts.PRESENCE_CUSTOM_STATUS_TIMESTAMP, 473a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov StatusUpdatesColumns.TIMESTAMP 474a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " AS " + Contacts.PRESENCE_CUSTOM_STATUS_TIMESTAMP); 4754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 4774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 4784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 4794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 4804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 4814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 4824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 4834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 4844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 4854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 4864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 4874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 4884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 4894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 4904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 4914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 4924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 4934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 4944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 4954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 4962815f58f72f109790585931f601a63ddc02536a5Evan Millar 4974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 4984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 4994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 5004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 5064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 5074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 5084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 5094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 5104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 5114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 5124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 5134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 5144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 5154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 5164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 5174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 5184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 5194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 5204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 5244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 53056d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 5384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 539a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 5415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 5425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 5435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 5445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 5505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 5515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 5525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 5535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 5545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 5555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 5565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 5575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 5585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 5595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 5605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 5615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 5625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 5635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 5645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 5685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5698f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 5775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 5785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 5795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 580e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 581e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 582e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_ID + " AS " + PhoneLookup._ID); 58356d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 58456d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar Contacts.LOOKUP_KEY + " AS " + PhoneLookup.LOOKUP_KEY); 585e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 586e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + PhoneLookup.DISPLAY_NAME); 587e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 588e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 589e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 590e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 591e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " + PhoneLookup.TIMES_CONTACTED); 592e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 593e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_STARRED + " AS " + PhoneLookup.STARRED); 594e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 595e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 596e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 597e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.PHOTO_ID + " AS " + PhoneLookup.PHOTO_ID); 598e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 599e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " + PhoneLookup.CUSTOM_RINGTONE); 600e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 601e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.HAS_PHONE_NUMBER + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 602e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 603e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 604e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 605e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 606e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 607e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 608e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 609e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 610e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 6119261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 612e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov HashMap<String, String> columns; 6137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 614ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 615ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 61689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 617035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 618035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 6199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 6209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 6219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 62289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 623ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 62467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 625ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 6263cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 62794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 6283cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 62938446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 63089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 63189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 63289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 63389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 634ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 635ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 6366cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 637ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 638ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 639d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 640d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 641ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 642ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 643ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 644d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 645d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 646ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 647f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 648ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 649ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 650b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 651b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 652b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 653b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 6540c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 6550c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 656b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 657b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 658eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 659eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 660eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 661eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 662eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 663eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 664341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 665341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 666341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 667fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 668341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 669341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 670341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 67168936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 67268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 67368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 67468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 67568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 676e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 67768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 67868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 67968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 680eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 681eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 682373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 683373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence._ID, Presence._ID); 6844dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 685373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.DATA_ID, Presence.DATA_ID); 686373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_ACCOUNT, Presence.IM_ACCOUNT); 687373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_HANDLE, Presence.IM_HANDLE); 6884dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(Presence.PROTOCOL, Presence.PROTOCOL); 68970c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 69070c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 69170c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov columns.put(Presence.CUSTOM_PROTOCOL, "(CASE WHEN " + Presence.CUSTOM_PROTOCOL 69270c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov + "='' THEN NULL ELSE " + Presence.CUSTOM_PROTOCOL + " END) AS " 69370c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov + Presence.CUSTOM_PROTOCOL); 694373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.PRESENCE_STATUS, Presence.PRESENCE_STATUS); 695a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov columns.put(Presence.PRESENCE_CUSTOM_STATUS, 696a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov StatusUpdatesColumns.STATUS + " AS " + Presence.PRESENCE_CUSTOM_STATUS); 697a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov columns.put(Presence.PRESENCE_CUSTOM_STATUS_TIMESTAMP, 698a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov StatusUpdatesColumns.TIMESTAMP + " AS " + Presence.PRESENCE_CUSTOM_STATUS_TIMESTAMP); 699373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov sPresenceProjectionMap = columns; 700373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov 701a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap = new HashMap<String, String>(); 702a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap.putAll(sDataProjectionMap); 703a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap.put(Presence.PRESENCE_STATUS, 704e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov Presence.PRESENCE_STATUS); 705a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap.put(Presence.PRESENCE_CUSTOM_STATUS, 706a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov StatusUpdatesColumns.STATUS + " AS " + Presence.PRESENCE_CUSTOM_STATUS); 707a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov sDataWithPresenceProjectionMap.put(Presence.PRESENCE_CUSTOM_STATUS_TIMESTAMP, 708a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov StatusUpdatesColumns.TIMESTAMP + " AS " + Presence.PRESENCE_CUSTOM_STATUS_TIMESTAMP); 70919a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 7101b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 7111b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 7121b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 7131b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 7141b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 7151b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 7161b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 7171b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 7181b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 7191b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 7201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 7211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 7224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsInGroupSelect = Contacts._ID + " IN " 7234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 7244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 7254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 7264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 7274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 7284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 7294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 7304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 7314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " FROM " + Tables.GROUPS 7324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 7334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 7344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 7353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 7363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 7373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 7383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 7393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 741653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 7423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 7443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 745a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 746a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 747a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 748a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 749a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 750a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 751a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 752a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 7533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 755653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 756653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 757653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mMimetypeId = mOpenHelper.getMimeTypeId(mMimetype); 758653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 759653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 760653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 761653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 7623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 7633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 7643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 7655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 766e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 767e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 768e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 769e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 770653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 771e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 772e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 773e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 7743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 7773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 7783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 7793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 780653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 781f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 78214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 78314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 784653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 785653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 786653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 787653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 788653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 789653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 790653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 791653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 792653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 793653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 794653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 795653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 796653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 797653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 798653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 799653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 800653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 801653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " = " + dataId, null); 802653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 803653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 804f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 805653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 806653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 8073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 81014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 81114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 81214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 8133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 8143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 8155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 8163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 8183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 8215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long newPrimaryId = findNewPrimaryDataId(db, rawContactId); 8223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (newPrimaryId != -1) { 82314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov setIsPrimary(rawContactId, newPrimaryId, getMimeTypeId()); 8243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected long findNewPrimaryDataId(SQLiteDatabase db, long rawContactId) { 828e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 829e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 8305ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Cursor c = queryData(db, rawContactId); 8313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 832e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 83314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 834f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 835e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 836e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 837e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 838e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 8393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 8413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 8423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 843e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return primaryId; 844e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 845e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 846e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 847e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 848e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 849e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 850e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 851e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 8523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected Cursor queryData(SQLiteDatabase db, long rawContactId) { 85514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return db.query(DataDeleteQuery.TABLE, DataDeleteQuery.CONCRETE_COLUMNS, 85614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId + 85714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " AND " + MimetypesColumns.MIMETYPE + "='" + mMimetype + "'", 8583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov null, null, null, null); 8593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 86125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 8623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String bestDisplayName = null; 86325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 86425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov 86567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Cursor c = db.query(DisplayNameQuery.TABLE, DisplayNameQuery.COLUMNS, 8665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId, null, null, null, null); 8673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 8683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov while (c.moveToNext()) { 8693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String mimeType = c.getString(DisplayNameQuery.MIMETYPE); 870a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 871a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // Display name is at DATA1 in all type. This is ensured in the constructor. 872a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String name = c.getString(DisplayNameQuery.DATA); 873a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (TextUtils.isEmpty(name) 874a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka && Organization.CONTENT_ITEM_TYPE.equals(mimeType)) { 875a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka name = c.getString(DisplayNameQuery.TITLE); 8763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 877a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka boolean primary = StructuredName.CONTENT_ITEM_TYPE.equals(mimeType) 878a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || (c.getInt(DisplayNameQuery.IS_PRIMARY) != 0); 8793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 88001911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (name != null) { 88125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov Integer source = sDisplayNameSources.get(mimeType); 88201911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (source != null 88301911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov && (source > bestDisplayNameSource 88401911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov || (source == bestDisplayNameSource && primary))) { 88525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov bestDisplayNameSource = source; 8863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov bestDisplayName = name; 8873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 8923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 8933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 89525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov setDisplayName(rawContactId, bestDisplayName, bestDisplayNameSource); 896285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 897285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateDisplayName(db, rawContactId); 898285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 8993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 900a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 901a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 902a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return true; 903a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 904622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 905622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 906622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 907622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * as baseline, but augmented with any updates. 908622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 909622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 910622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 911622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 912622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=" + dataId, 913622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey null, null, null, null); 914622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 915622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 916622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 917622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 918622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.put(key, cursor.getString(i)); 919622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 920622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 921622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 922622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 923622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 924622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 925622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 926622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 9273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 9303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 9323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 9333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 937622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 9383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 939622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 9403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 941622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 9423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 9455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 946622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 94714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 94814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 94914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 950f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 951f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 95225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 95314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 95414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 95514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 95614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 95714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 958f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 959622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 960622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 961cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 962622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 963622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 96414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 965f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 96614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 967f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 968f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 969f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 970f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 97114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 97225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 97314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 97414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 97514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 97614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 97714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 97814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 97914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 98014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 98114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 982f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 98325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 98414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 9853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 988622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 9893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 990622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 991622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 992622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 993622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 9943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 995622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 996622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 997622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 998622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 999622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1000622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1001622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 1002622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1003622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1004622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 1005622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1006622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1007622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 10088c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1009622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1010622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 1011622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } else if (!touchedUnstruct && touchedStruct) { 10128c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1013622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 1014622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(name); 1015622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 1016622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1017622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1018622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1019622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1020622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1021622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1022622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1023622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1024622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1025622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1026622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1027622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1028622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1029622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1030622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1031622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1032622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1033622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1034622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1035622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1036f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1037622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1038622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1039622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1040f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1041622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1042622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1043622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1044622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1045622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1046622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1047622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1048622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1049622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1050622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1051622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1052622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1053622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1054622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1055622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1056622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1057622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1058622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 1059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 1060622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1061622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 1062622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1063622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1064622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1065622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1066622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1067622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1068622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 1069622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } else if (!touchedUnstruct && touchedStruct) { 1070622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1071622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1072622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 10733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 10783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 10803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 10813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 10833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 10853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 10863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 10895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1090622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1091622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1092622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1094622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1095622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1096f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1097622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1098622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1099622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1100f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1101622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1103622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1104622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1105622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1106622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1107622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1108622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1109622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1110622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 11113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1112622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1113622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1114622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1115622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1116622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 11213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 11233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 11243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1128a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1129a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1130a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1131a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1132a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 113325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1134a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1135a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 11363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 113914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1140f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1141a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1142a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1143a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 114414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 114514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1146f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 114714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 114825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1149a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 1150a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 115114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 115214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 115314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 115414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1155a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 115614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 115714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 115814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 115925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1160a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 116114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 116214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 116314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 116414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 11653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 11663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 11673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 11683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 11693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 11703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 11713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1173a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1174a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1175a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1176a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1177a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 11783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1180e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1181e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1182e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1183e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1184e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1185e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1186e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 11875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 118814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 118914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 119014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 119114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 119225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1193f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 119414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 119514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 119614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 119714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 119814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1199f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 120014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 120114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 120214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 120314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1204f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 120514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1206f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1207f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 120825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 120914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 121014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 121114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 121214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 121314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 121414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 121514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 121614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 121714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1218f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 121925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 122014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1221e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1222e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1223e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1224e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1225e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1226e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1227e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1228e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1229e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1230e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1231e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1232e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1233e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1234e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 123514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 123614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 123714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 123814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 123914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 124014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 124114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 124214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 124314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 124414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 124514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 124614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 124725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1248f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 124914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 125014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 125114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 125214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 125314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1254f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 125514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 125614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 125714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 125814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1259f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 126014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1261f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1262f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 126325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 126414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 126514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 126614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 126714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 126814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 126914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 127014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 127114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 127214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1273f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 127425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 127514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 127614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 127714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 127814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 12793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 12803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 12823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 12833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 12870b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 12880b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 12890b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 12900b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1291653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 12920b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1293653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 12940b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1295285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 129625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 12970b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 12980b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 12990b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1300653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1301653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1302653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1303653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1304653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1305f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 130614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 130714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 13080b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 13090b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 13100b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1311653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1312f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1313653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 13140b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1315285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 131625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 13170b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 1318f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 13190b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 132014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 132114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 132214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 132314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 132414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 132514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 132614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 132714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 132814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 132914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1330285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 133125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 133214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1333653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1334653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1335653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1336e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1337e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1338e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1339e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1340653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1341653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1342653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1343e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1344653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1345653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1346e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1347653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 13485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1349653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1350e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 1351653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1352653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1353653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=" + dataId, null); 1354e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 13553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 13593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 13603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 13613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 13623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 13633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 13643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 13653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 13663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 13673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 13683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 13693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1373653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1374653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1375653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1376653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1377653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1378653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1379653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1380653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1381653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 13820be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 13830be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 13840be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1385653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1386653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1387653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1388653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1389f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 139014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1391653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1392f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 13930be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 13940be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 13950be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 13960be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 13970be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 13980be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 13990be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 14000be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 14010be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 14020be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 14030be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 14040be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 14050be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 14060be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 14070be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov mOpenHelper.updateContactVisible(contactId); 14080be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1409653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1410653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1411653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1412653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1413653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1414653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1415653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1416653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1417653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1418653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1419653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1420653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1421653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1422653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1423653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1424653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1425653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1426653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1427653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1428653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1429653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1430653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1431653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1432653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1433653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId); 1434653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1435653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1436653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1437653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1438a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1439a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1440a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1441a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1442a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1443653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1444653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1445a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1446a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1447a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1448a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1449a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1450a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1451a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1452a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1453a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1454285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1455285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1456285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1457a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1458a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1459a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1460a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1461a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1462f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1463a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1464f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1465a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1466a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1467a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1468a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1469a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1470a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1471a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1472a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1473a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1474a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1475a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1476a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1477a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1478a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1479a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1480a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1481a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1482a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 14833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 148453056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 14854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private OpenHelper mOpenHelper; 148631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 14874097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1488f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1489f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private HashMap<String, SoftReference<String[]>> mNicknameClusterCache = 1490f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov new HashMap<String, SoftReference<String[]>>(); 1491622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1492622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1493622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1494f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1495a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1496a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 149720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 149820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1499ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 150073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private boolean mImportMode; 150173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1502b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mInsertedRawContacts = Sets.newHashSet(); 1503b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1504b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1505de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 150681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 150781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 1508a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 150953056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 1510a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1511a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1512a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1513a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 1514a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 151553056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 151653056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 1517a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 15184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 15194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 15204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1521de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 152235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1523de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1524de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mOpenHelper = (OpenHelper)getOpenHelper(); 1525a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1526a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mOpenHelper, this, mGlobalSearchSupport); 1527cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov mContactAggregator = new ContactAggregator(this, mOpenHelper, mAggregationScheduler); 15280e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1529a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1530d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 1531653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1532c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1533653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1534653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1535653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1536653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1537653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1538c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1539653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1540653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1541653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1542653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1543653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1544653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1545653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1546653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1547653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1548653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1549653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 15505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mLastTimeContactedUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 15516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.TIMES_CONTACTED + "=" + RawContacts.TIMES_CONTACTED + "+1," 1552d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + RawContacts.LAST_TIME_CONTACTED + "=? WHERE " + RawContacts.CONTACT_ID + "=?"); 1553a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 155425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate = db.compileStatement( 155525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 155625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " SET " + RawContactsColumns.DISPLAY_NAME + "=?," 155725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov + RawContactsColumns.DISPLAY_NAME_SOURCE + "=?" + 155825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 15593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 156073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 156173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + RawContacts.DIRTY + "=1 WHERE " + RawContacts._ID + "=?"); 156273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1563a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate = db.compileStatement( 1564a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.CONTACTS 1565a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1566a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1567a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1568a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1569a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1570a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1571a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1572a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1573a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1574a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 1575a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ORDER BY " + StatusUpdatesColumns.TIMESTAMP + " DESC" + 1576a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LIMIT 1)" 1577a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1578e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1579622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Locale locale = Locale.getDefault(); 158028f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 158128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 158228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 158328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 1584622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey context.getString(com.android.internal.R.string.common_name_conjunctions), 1585622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey locale); 1586f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 1587622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mPostalSplitter = new PostalSplitter(locale); 15884097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1589f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1590f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1591f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1592f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1593f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1594f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1595f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1596a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert = db.compileStatement( 1597a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1598a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 1599a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.TIMESTAMP + "," 1600a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.STATUS + ")" + 1601a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " VALUES (?,?,?)"); 1602a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1603a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace = db.compileStatement( 1604a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1605a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 1606a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.TIMESTAMP + "," 1607a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.STATUS + ")" + 1608a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " VALUES (?,?,?)"); 1609a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1610a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp = db.compileStatement( 1611a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 1612a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " SET " + StatusUpdatesColumns.TIMESTAMP + "=?," 1613a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.STATUS + "=?" + 1614a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 1615a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " AND " + StatusUpdatesColumns.STATUS + "!=?"); 1616a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1617a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete = db.compileStatement( 1618a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1619a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1620a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 16213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 16223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1623e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 16243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 16253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 162667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 162767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 16283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 16293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 163014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 16313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 16323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1633622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1634622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1635a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1636a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 16373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 16383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1639568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 16403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1641568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1642c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov verifyAccounts(); 164370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 16441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 16454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 16464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1647c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 1648c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1649c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1650c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 1651c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 165231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1653de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 165431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov protected OpenHelper getOpenHelper(final Context context) { 165531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov return OpenHelper.getInstance(context); 165631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 165731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1658285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov /* package */ ContactAggregationScheduler getContactAggregationScheduler() { 1659285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mAggregationScheduler; 1660285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1661285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1662013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1663013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1664013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1665013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 16663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 16673d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 16683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 16693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 16703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1671568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1672568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1673568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1674568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1675568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1676568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1677568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1678568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1679568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1680ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1681568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1682568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1683568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1684568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1685568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1686568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1687568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1688568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1689568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1690568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1691ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1692ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1693568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov scheduleContactAggregation(); 1694568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1695568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1696568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1697568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1698568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1699568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1700568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 17013d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1702568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1703568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 17043d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 17053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 17063d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 17073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 17083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 17093d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 17103d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 17113d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 17123d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 17133d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 17143d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1715568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 17160e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 17173d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 171873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = true; 17193d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 17203d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 17210e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(aggregatorEnabled); 17223d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 17233d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 17243d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 17253d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 172673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } finally { 172773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = false; 17283d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 17293d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 17303d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1731a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1732a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 1733a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 1734a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 1735a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1736a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1737a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 1738a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1739a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1740a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1741a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1742a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1743a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1744a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mOpenHelper.wipeData(); 1745a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1746a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1747568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1748568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 1749568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1750568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1751568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1752568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1753568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1754568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 1755ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 1756ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 1757ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 1758ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 1759ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 1760ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1761ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 1762ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 176381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 1764ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1765ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1766568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1767568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1768568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1769568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1770568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1771568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1772568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1773568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1774568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1775568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1776568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1777568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1778568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1779568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1780568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1781568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1782568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 1783568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1784568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1785568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1786568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1787568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1788568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1789568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 1790568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1791568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1792568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1793568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 17944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1795285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1796bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1797b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1798b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1799285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 18001ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1801b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1802b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1803b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1804b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 1805285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 1806b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 1807df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 1808285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1809285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1810285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1811285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 1812bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1813b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1814b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1815285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1816b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 18171ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 1818b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1819b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1820b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1821bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1822b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1823b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1824b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long rawContactId : mInsertedRawContacts) { 1825b5a4add17815167d20a90645779df34cdf45280dFred Quintana mContactAggregator.insertContact(mDb, rawContactId); 1826285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1827b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1828b5a4add17815167d20a90645779df34cdf45280dFred Quintana String ids; 1829b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 1830b5a4add17815167d20a90645779df34cdf45280dFred Quintana ids = buildIdsString(mUpdatedRawContacts); 1831b5a4add17815167d20a90645779df34cdf45280dFred Quintana mDb.execSQL("UPDATE raw_contacts SET version = version + 1 WHERE _id in " + ids, 1832b5a4add17815167d20a90645779df34cdf45280dFred Quintana new Object[]{}); 1833b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1834b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1835b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 1836b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 1837b5a4add17815167d20a90645779df34cdf45280dFred Quintana mOpenHelper.getSyncState().update(mDb, id, entry.getValue()); 1838b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1839b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1840b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1841b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1842b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1843b5a4add17815167d20a90645779df34cdf45280dFred Quintana private String buildIdsString(HashSet<Long> ids) { 1844b5a4add17815167d20a90645779df34cdf45280dFred Quintana StringBuilder idsBuilder = null; 1845b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 1846b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (idsBuilder == null) { 1847b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder = new StringBuilder(); 1848b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append("("); 1849b5a4add17815167d20a90645779df34cdf45280dFred Quintana } else { 1850b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(","); 1851b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1852b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(id); 1853b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1854b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(")"); 1855b5a4add17815167d20a90645779df34cdf45280dFred Quintana return idsBuilder.toString(); 1856285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1857285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1858285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1859cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 186081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 186181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 186281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 186381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 186481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 186581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 186681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 1867cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 1868568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1869568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected void scheduleContactAggregation() { 1870dee54bb86f3608730f0b9f37d8982a7f6b280a85Dmitri Plotnikov mContactAggregator.schedule(); 1871568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1872568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1873285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 1874285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mInsertedRawContacts.contains(rawContactId); 1875285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1876285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 18773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 18783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 18793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 18803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 18813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 18823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 18833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 18843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 18853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 18864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1887de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 1888bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1889b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "insertInTransaction: " + uri); 1890b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1891f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1892f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 1893f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 1894f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1895a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 1896a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 189735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1898a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 189935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 1900de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov id = mOpenHelper.getSyncState().insert(mDb, values); 190135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 190235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1903d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1904d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 19056bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 19066bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 19076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 19085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 1909f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 1910d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov id = insertRawContact(values, account); 1911f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1912a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1913a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1914a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 19155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 19165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 1917f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1918f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1919a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1920a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1921a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1922a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 1923f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1924f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1925a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1926a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1927a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1928ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1929ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 19305aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertGroup(uri, values, account, callerIsSyncAdapter); 1931f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1932ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1933ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1934ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1935eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 19365aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 193743880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 1938eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 1939eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 1940eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 19411f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 19421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey id = insertPresence(values); 19431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 19441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 19451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1946a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 194781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 1948f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 1949a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1950a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 19517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 19527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 19537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 19547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1955de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 1956a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1957a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1958a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1959035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 1960035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 1961035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 1962035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 1963035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 19647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 1965035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 1966035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 19676cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME); 19686cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 1969035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 1970035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 1971035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 1972035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 1973035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1974035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 1975035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1976035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 1977df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_NAME, account.name); 1978df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_TYPE, account.type); 1979035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1980035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 19817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 19827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 19837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 1984d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 19856bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 19866bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 19876bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 19886bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1989d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 1990de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 19916bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 19926bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 19936bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 1994a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 1995a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1996a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1997f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 1998a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1999a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2000d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertRawContact(ContentValues values, Account account) { 2001a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 2002d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov overriddenValues.putNull(RawContacts.CONTACT_ID); 2003f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 20047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 20057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 20067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 20073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 20083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 20093d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov overriddenValues.put(RawContacts.AGGREGATION_MODE, 20103d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DISABLED); 20113d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 20123d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2013023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov long rawContactId = 2014023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, overriddenValues); 2015023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 2016285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2017285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2018285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.add(rawContactId); 2019023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2020a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2021a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2022a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2023a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2024a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2025a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2026a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2027a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2028f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2029a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2030de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2031de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 203267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2033de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 203420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2035de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2036de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2037de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2038de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 2039de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2040de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2041508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2042de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2043de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2044de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2045de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2046de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 20474097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2048de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mOpenHelper.getMimeTypeId(mimeType)); 2049de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2050a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2051a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2052a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2053f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2054de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2055a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2056b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2057a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2058a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2059a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2060a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2061a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 20624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 20634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 20648e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 20658e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 20668e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 20678e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 20688e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 20698e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov int aggregationMode = mOpenHelper.getAggregationMode(rawContactId); 2070f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 20718e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 20728e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 20738e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 20748e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2075421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 2076f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 20778e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 20788e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 20798e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 20808e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 2081f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 20828e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 20838e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 20848e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2085f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 20868e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2087f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2088c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 20898e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 20908e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2091f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 20928e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2093f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2094f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2095f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2096a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 20975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 20989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 20999261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 21005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 21019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 21029261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 21039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 21049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 21059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 21065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId) { 21079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Account account = null; 21086cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts._ID + "=" 21095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId, null, null, null, null); 21109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 21119261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 211267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountName = c.getString(ContactsQuery.ACCOUNT_NAME); 211367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountType = c.getString(ContactsQuery.ACCOUNT_TYPE); 21149261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 21159261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana account = new Account(accountName, accountType); 21169261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21189261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 21199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 21209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 21229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 21239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "has a sourceid the the contact must be associate with " 21249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 21259261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21269261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 21279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 21285ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 21296cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 21309261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2131df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 21329261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 21339261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 21349261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return c.getLong(0); 21359261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 21369261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2137df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2138df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 21399261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 21409261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 21419261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 21429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 21439261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 21449261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21459261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return groupId; 21469261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21479261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 21489261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 21499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21519261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 21529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 215320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 215420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2155f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 215620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 215720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2158de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2159de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 216014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2161de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2162de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 216314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 216414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2165a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2166a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2167f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 216888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 2169a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2170a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2171a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 217288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 217320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 217420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2175de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 217620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 217720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 217820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 217920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 218020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 218188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 218288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 218388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 218420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2185f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 218688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 218788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 218814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=" + dataId, null, 218914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov null); 2190f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 219120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 219220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 219320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 219420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 219520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 219614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 219720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 219820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 219920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 220020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 220120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 220220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 220320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 220420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 220520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 22067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 220720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 220820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 220920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2210a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2211a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 22128e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2213a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2214a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2215a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 22168e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 221720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 221820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 221920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 222020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 222120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 222220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 22235aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey * Determine if the given {@link Uri} and {@link ContentValues} should 22245aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey * trigger a call to {@link OpenHelper#updateAllVisible()}, usually based on 22255aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey * query parameters like {@link Contacts#DELAY_STARRED_UPDATE} and columns 22265aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey * like {@link Groups#GROUP_VISIBLE}. 22275aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey */ 22285aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private boolean shouldUpdateAllVisible(Uri uri, ContentValues values, String visibleColumn) { 22295aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey final boolean delayUpdate = readBooleanQueryParameter(uri, 22305aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey Contacts.DELAY_STARRED_UPDATE, false); 22315aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey final boolean forceUpdate = readBooleanQueryParameter(uri, 22325aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey Contacts.FORCE_STARRED_UPDATE, false); 22335aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey final boolean touchedVisible = (values == null) ? true : values.containsKey(visibleColumn); 22345aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 22355aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return forceUpdate || (!delayUpdate && touchedVisible); 22365aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey } 22375aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 22385aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey /** 22395aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey * Determine if the given {@link Uri} and {@link ContentValues} should 22405aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey * trigger a call to {@link OpenHelper#updateAllVisible()}, usually based on 22415aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey * query parameters like {@link Contacts#DELAY_STARRED_UPDATE}. 22425aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey */ 22435aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private boolean shouldUpdateAllVisible(Uri uri) { 22445aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return shouldUpdateAllVisible(uri, null, null); 22455aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey } 22465aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 22475aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey /** 2248ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2249ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 22505aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertGroup(Uri uri, ContentValues values, Account account, boolean callerIsSyncAdapter) { 2251ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 2252ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 2253ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 2254ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2255ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2256ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 225767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.RES_PACKAGE); 225867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 225967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.put(GroupsColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 226067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 226167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.remove(Groups.RES_PACKAGE); 2262ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2263f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 226473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov overriddenValues.put(Groups.DIRTY, 1); 226573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 226673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2267ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey long result = mDb.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 2268ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 22695aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey if (shouldUpdateAllVisible(uri, overriddenValues, Groups.GROUP_VISIBLE)) { 2270ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey mOpenHelper.updateAllVisible(); 2271ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2272ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2273ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2274ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2275ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 22765aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2277e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 22785aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 22795aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey if (shouldUpdateAllVisible(uri, values, Settings.UNGROUPED_VISIBLE)) { 2280e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mOpenHelper.updateAllVisible(); 2281e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2282e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2283e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2284e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2285ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 22861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey * Inserts a presence update. 22871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 228870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public long insertPresence(ContentValues values) { 22891f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final String handle = values.getAsString(Presence.IM_HANDLE); 22904dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(handle) || !values.containsKey(Presence.PROTOCOL)) { 22914dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 22924dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 22934dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 22944dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov final long protocol = values.getAsLong(Presence.PROTOCOL); 22954dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 22964dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 22974dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (protocol == Im.PROTOCOL_CUSTOM) { 22984dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov customProtocol = values.getAsString(Presence.CUSTOM_PROTOCOL); 22994dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 23004dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 23014dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 23024dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 23031f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 23041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 23051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // TODO: generalize to allow other providers to match against email 23064dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 23071f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 230870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov StringBuilder selection = new StringBuilder(); 23091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String[] selectionArgs; 23101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (matchEmail) { 23114dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append( 23124dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "((" + MimetypesColumns.MIMETYPE + "='" + Im.CONTENT_ITEM_TYPE + "'" 23134dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.PROTOCOL + "=?" 23144dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.DATA + "=?"); 23154dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (customProtocol != null) { 23164dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 23174dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(selection, customProtocol); 23184dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 23194dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append(") OR (" 23204dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + MimetypesColumns.MIMETYPE + "='" + Email.CONTENT_ITEM_TYPE + "'" 23214dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Email.DATA + "=?" 23224dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + "))"); 23234dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selectionArgs = new String[] { String.valueOf(protocol), handle, handle }; 23241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 23254dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append( 23264dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov MimetypesColumns.MIMETYPE + "='" + Im.CONTENT_ITEM_TYPE + "'" 23274dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.PROTOCOL + "=?" 23284dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.DATA + "=?"); 23294dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (customProtocol != null) { 23304dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 23314dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(selection, customProtocol); 23324dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 23334dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 23344dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selectionArgs = new String[] { String.valueOf(protocol), handle }; 23351f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 23361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 233770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (values.containsKey(Presence.DATA_ID)) { 233870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.append(" AND " + DataColumns.CONCRETE_ID + "=") 233970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov .append(values.getAsLong(Presence.DATA_ID)); 234070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 234170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 234200ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey selection.append(" AND ").append(getContactsRestrictions()); 234370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 23441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long dataId = -1; 23455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = -1; 2346e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov long contactId = -1; 234770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 23481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 23491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2350de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 235170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.toString(), selectionArgs, null, null, null); 23521f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 235367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 23545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2355e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 23561f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 23571f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 23581f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 23591f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 23601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 236131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 236231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 236331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 23641f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 23651f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2366a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (values.containsKey(Presence.PRESENCE_STATUS)) { 2367a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2368a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2369a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2370a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2371a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2372a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2373a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 2374a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // TODO deprecate and then remove the Presence._ID column 2375a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(Presence._ID, dataId); 2376a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(Presence.DATA_ID, dataId); 2377a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2378a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 2379a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(Presence.PROTOCOL, protocol); 2380a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(Presence.CUSTOM_PROTOCOL, customProtocol); 2381a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(Presence.IM_HANDLE, handle); 2382a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (values.containsKey(Presence.IM_ACCOUNT)) { 2383a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(Presence.IM_ACCOUNT, values.getAsString(Presence.IM_ACCOUNT)); 2384a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2385a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(Presence.PRESENCE_STATUS, values.getAsString(Presence.PRESENCE_STATUS)); 23861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2387a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2388a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2389a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2390e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 2391a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (values.containsKey(Presence.PRESENCE_CUSTOM_STATUS)) { 2392e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov String status = values.getAsString(Presence.PRESENCE_CUSTOM_STATUS); 2393a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 2394a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 2395a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 2396a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else if (values.containsKey(Presence.PRESENCE_CUSTOM_STATUS_TIMESTAMP)) { 2397a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov long timestamp = values.getAsLong(Presence.PRESENCE_CUSTOM_STATUS_TIMESTAMP); 2398a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 2399a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 2400a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindString(3, status); 2401a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 2402a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 2403a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov long timestamp = System.currentTimeMillis(); 2404a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2405a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 2406a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 2407a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(2, timestamp); 2408a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindString(3, status); 2409a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 2410a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 2411a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 2412a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 2413a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindString(2, status); 2414a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 2415a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindString(4, status); 2416a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 2417a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2418e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2419e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2420bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2421a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2422a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 2423a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 2424a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 2425a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2426a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2427a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 24281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 24304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2431de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2432bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2433b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2434b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2435b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2436f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2437f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2438508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2439508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 244035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2441de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mOpenHelper.getSyncState().delete(mDb, selection, selectionArgs); 244235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2443b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2444b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2445b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2446b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2447b5a4add17815167d20a90645779df34cdf45280dFred Quintana return mOpenHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2448b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2449cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2450cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2451cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2452cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2453cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2454d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2455d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2456cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 24576bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 24586bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 24592e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 24602e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 24612e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 24622e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 24632e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 24642e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 24652e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 24662e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 24672e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 24682e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 24692e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 24702e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 24712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 24722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 24732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2474e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 24752971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 24762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 24772971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2478f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana numDeletes += deleteRawContact(rawContactId, callerIsSyncAdapter); 24792971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 24802971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 24812971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 24822971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 24832971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 24842971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 24852971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 24865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 24872971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2488f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteRawContact(rawContactId, callerIsSyncAdapter); 2489508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2490508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 249120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2492f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2493944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2494f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 249520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 249620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 249748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 249848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 249948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 250048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2501508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2502f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2503f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteData(Data._ID + "=" + dataId, null, callerIsSyncAdapter); 2504ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2505ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2506ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2507f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 25085aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 25092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 25102971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 25112971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 25122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 25132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2514e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 25152971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 25162971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 25175aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 25182971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 25192971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 25202971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 25212971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 252281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2523f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 252481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 25252971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2526508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2527508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2528eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 252943880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 25305aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteSettings(uri, selection, selectionArgs); 2531eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2532eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 25331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 2534eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 25351f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 253781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 253881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 25393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 254081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2541508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 25424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 25434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 25442971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana private boolean readBooleanQueryParameter(Uri uri, String name, boolean defaultValue) { 25452971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final String flag = uri.getQueryParameter(name); 25462971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return flag == null 25472971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana ? defaultValue 25482971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana : (!"false".equals(flag.toLowerCase()) && !"0".equals(flag.toLowerCase())); 254994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 255094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 25515aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 255294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana final long groupMembershipMimetypeId = mOpenHelper 255394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2554de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 255594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 255694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 255794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 255894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2559f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2560de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 256194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 256294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 256394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2564f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2565de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 256694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 256794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 25685aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey if (shouldUpdateAllVisible(uri)) { 25695aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey mOpenHelper.updateAllVisible(); 25705aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey } 257194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 257294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 257394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 25745aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2575e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 25765aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey if (count > 0 && shouldUpdateAllVisible(uri)) { 2577e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mOpenHelper.updateAllVisible(); 2578e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2579e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2580e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2581e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2582cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 2583cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2584cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null); 2585cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2586cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2587cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2588cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 2589cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2590cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2591cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2592cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2593cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2594cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2595cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2596cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2597f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana public int deleteRawContact(long rawContactId, boolean callerIsSyncAdapter) { 2598f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 259914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2600de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 260133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2602a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov mOpenHelper.removeContactIfSingleton(rawContactId); 2603cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 260433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 260533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 260633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 2607cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 260881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 260981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 2610cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 2611cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 2612cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2613cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2614cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2615cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2616cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 2617cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2618cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 26194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2620de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2621de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 2622bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2623b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2624b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2625b5a4add17815167d20a90645779df34cdf45280dFred Quintana 262635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 262700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 262800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 2629b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 2630b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 2631b5a4add17815167d20a90645779df34cdf45280dFred Quintana Object data = values.get(ContactsContract.SyncStateColumns.DATA); 2632b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 2633b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 2634b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2635b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2636f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2637f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 263800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 263935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2640b5a4add17815167d20a90645779df34cdf45280dFred Quintana return mOpenHelper.getSyncState().update(mDb, values, 2641b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 2642b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2643b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 2644b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 2645b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2646b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2647b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2648b5a4add17815167d20a90645779df34cdf45280dFred Quintana return mOpenHelper.getSyncState().update(mDb, values, 2649b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 2650b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 265135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2652d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 26538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 265400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 265500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 265600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2657d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 26588c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 2659c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2660c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2661c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 26622e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 26632e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 26642e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 26652e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 26662e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 26672e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 26682e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26692e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 26702e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 26718c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 26722e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 26732e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26742e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 26757d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 26767d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 26777d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 26787d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 26797d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 26807d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 26817d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 26827d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 26837d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 26847d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 268520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2686944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2687f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 268881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2689f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 269081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 269120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 269220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2693c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 269448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 269548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 269648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 269748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2698f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 269981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2700f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 270181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 270200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 270300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 27047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 27055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 27065ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 27074529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 27087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 27097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 27107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 27115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 271233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 27134529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 27144529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=" + rawContactId 27154529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 27164529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 27174529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContact(rawContactId, values); 27184529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 27197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 27207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 27217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2722ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 27235aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 2724f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 272581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2726f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 272781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2728ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2729ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2730ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2731ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2732ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 273373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String selectionWithId = (Groups._ID + "=" + groupId + " ") 273473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 27355aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 27365aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 273781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2738f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 273981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2740ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2741ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2742ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2743127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 2744de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 2745b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2746b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2747b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2748eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 27495aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateSettings(uri, values, selection, selectionArgs); 275043880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2751eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2752eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2753eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 275481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 275581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2756f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 275781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 275800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 275900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 276000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 27614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 27635aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 2764f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 276573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 276673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 2767f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 276873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 276973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 277073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 277173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 277273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 277373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 277473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 277573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2776ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 277794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 277894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana // If changing visibility, then update contacts 27795aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey if (shouldUpdateAllVisible(uri, updatedValues, Groups.GROUP_VISIBLE)) { 278094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mOpenHelper.updateAllVisible(); 278194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 278294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 278394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 278494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 27855aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateSettings(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 2786e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 27875aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey if (shouldUpdateAllVisible(uri, values, Settings.UNGROUPED_VISIBLE)) { 2788e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mOpenHelper.updateAllVisible(); 2789e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2790e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2791e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2792e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 27934529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 27944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 27954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 27964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 27974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 279873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 27994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 28004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov Cursor cursor = mDb.query(mOpenHelper.getRawContactView(), 280151bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 28024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 28034529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 28044529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 28054529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 28064529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 28074529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 28084529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 28094529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 28104529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 28114529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 28124529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 28134529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 28144529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 28154529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 28164529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 28174529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = mDb.update(Tables.RAW_CONTACTS, values, RawContacts._ID + " = " + rawContactId, 28184529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov null); 28195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 2820433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 28214529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 2822433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 2823285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 2824285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateLookupKey(mDb, rawContactId); 2825285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 28265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 28275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 282833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 282933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 2830321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 2831f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 283220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 283320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 283420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 28355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 283620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 283720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 283820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 283920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 284020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 284120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 284220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 284320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 284470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 284570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 284620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 284720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 284820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 284970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 285020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 285170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 285220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 285370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 285420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 285570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 285620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 285720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2858653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 285920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2860653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2861653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 286214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 2863653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 2864653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 2865f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 286620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2867653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 2868653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 286920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 287020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2871653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 287220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 287320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2874f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 2875653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 2876653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 2877321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2878653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 287914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 2880a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2881f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana rowHandler.update(mDb, values, c, callerIsSyncAdapter); 28828e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 2883a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2884a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2885a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 28868e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2887653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 2888321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2889321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 28908c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 28918c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 28928c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 28938c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov Cursor cursor = mDb.query(mOpenHelper.getContactView(), 28948c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 28958c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 28968c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 28978c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 28988c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 28998c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 29008c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 29018c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 29028c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 29038c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 29048c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 29058c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 29068c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 29078c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 29088c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 29098c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 2910d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 29118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 29128c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 2913d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 29148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 2915d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 29168c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 2917d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 29188c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 2919d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 29208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.STARRED, 2921d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 2922d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2923d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 29248c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 2925d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 2926d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2927d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 29288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 2929c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 29308c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2931c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 2932c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 29338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=" + contactId, null); 29348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 29358c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 29368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 29378c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 29388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 29398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 29408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 29418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 29428c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 29438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 29448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 29458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 29468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.STARRED, 29478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 29488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 29498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=" + contactId, null); 2950f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2951d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2952d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public void updateContactTime(long contactId, long lastTimeContacted) { 2953f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 2954d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(2, contactId); 2955f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.execute(); 2956d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2957d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2958127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 2959127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 29600c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 29610c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 296280c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 29630c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 29640c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 29650c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 29660c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 29670c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 29680c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 29690c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 2970b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2971127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 29720c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 29730c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 29740c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=" + rawContactId1 + " AND " 29750c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=" + rawContactId2, null); 29760c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 29776bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 29786bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 29790c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 29800c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 29810c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 29820c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 2983127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2984127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2985dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 2986dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 2987dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 29880c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long contactId1 = mOpenHelper.getContactId(rawContactId1); 29890c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 29900c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 29910c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long contactId2 = mOpenHelper.getContactId(rawContactId2); 29920c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 2993127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2994127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 2995127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 2996127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 2997b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2998b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 299970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 300070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb = mOpenHelper.getWritableDatabase(); 300170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (mDb == null) return; 300270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 300370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong Set<Account> validAccounts = Sets.newHashSet(); 300470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accounts) { 300570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong validAccounts.add(new Account(account.name, account.type)); 300670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 300770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong ArrayList<Account> accountsToDelete = new ArrayList<Account>(); 300870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 300970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 301070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 301148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 30125f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana for (String table : new String[]{Tables.RAW_CONTACTS, Tables.GROUPS, Tables.SETTINGS}) { 30135f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // Find all the accounts the contacts DB knows about, mark the ones that aren't 30145f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // in the valid set for deletion. 30155f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Cursor c = mDb.rawQuery("SELECT DISTINCT account_name, account_type from " 30165f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + table, null); 30175f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana while (c.moveToNext()) { 30185f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (c.getString(0) != null && c.getString(1) != null) { 30195f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Account currAccount = new Account(c.getString(0), c.getString(1)); 30205f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (!validAccounts.contains(currAccount)) { 30215f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana accountsToDelete.add(currAccount); 30225f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana } 302370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 302470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 30255f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana c.close(); 302670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 302770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 302870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 30295f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 303070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong String[] params = new String[]{account.name, account.type}; 303170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.GROUPS 303270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 303370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.PRESENCE 303470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (SELECT " 303570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS 303670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?)", params); 303770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.RAW_CONTACTS 303870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 30395f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana mDb.execSQL("DELETE FROM " + Tables.SETTINGS 30405f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + " WHERE account_name = ? AND account_type = ?", params); 304170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 30424637c20c6b6d3b6f6671e6a44ed57f1e5b9c4484Dmitri Plotnikov mOpenHelper.getSyncState().onAccountsChanged(mDb, accounts); 304370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 304470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 304570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 304670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 304770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3048619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3049619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3050622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 3051622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 3052622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private static boolean areAllEmpty(ContentValues values, String[] keys) { 3053622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 3054622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (!TextUtils.isEmpty(values.getAsString(key))) { 3055622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return false; 3056622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3057622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3058622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return true; 3059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3060622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 30614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 30624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 30634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 3064bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3065bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3066bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 30670b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 30684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 306935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3070d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 30711f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3072c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3073c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3074619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3075619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3076a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 30774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 307835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 307935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().query(db, projection, selection, selectionArgs, 308035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 308135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3082d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3083ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 3084619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3085619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3086619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3087d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 30884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3089ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 30904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + contactId); 30916bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 30926bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 30936bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 30945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 30955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 30965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 30975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 30985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 30995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 31005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 31025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 31035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 31045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 31055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov setTablesAndProjectionMapForContacts(lookupQb, projection); 31065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=" + contactId + " AND " + 31075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.LOOKUP_KEY + "="); 31085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhereEscapeString(lookupKey); 31095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, selectionArgs, sortOrder, 31105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 31115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 31125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 31135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 31155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 31165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 31185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 31195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 31205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 31215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3123ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3124ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 3125ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 31264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 31274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3128e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 31295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 31304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sb.toString()); 3131ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3132ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3133ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3134ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3135ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3136ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 31374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3138ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3139d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 31404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 31414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3142e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 31435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 31444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 31454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 31464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3147ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 3148ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 31494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 31504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 31514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3152d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final String starredQuery = qb.buildQuery(projection, Contacts.STARRED + "=1", 31544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3155d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3156d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3157d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3158ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 31594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 31604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3161d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3162d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String frequentQuery = qb.buildQuery(projection, 3163d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3164d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 31654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3166d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3167d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3168d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3169d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 31704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 31714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3172d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3173d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3174d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3175d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3176d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3177d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3178ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3179ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 3180b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 31814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sContactsInGroupSelect); 31824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3183b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3184b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3185b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3186b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3187d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 31884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 31894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 31904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 31914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 31924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov appendAccountFromParameter(qb, uri); 31934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 31946bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 31956bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 319600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3197ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 31983653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 31993653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 32003653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 32013653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 32023653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov appendAccountFromParameter(qb, uri); 32033653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 32043653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 32053653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 32063653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 32073653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 32084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 32094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 32104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 321189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 321289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 32132815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 32142815f58f72f109790585931f601a63ddc02536a5Evan Millar } 32152815f58f72f109790585931f601a63ddc02536a5Evan Millar 321648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 321748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 321848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 321948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov appendAccountFromParameter(qb, uri); 322048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 322148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 322248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 322348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 322448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3225ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 32264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 32275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.setProjectionMap(sDistinctDataProjectionMap); 322889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 322989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3230ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 32314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 32324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 32335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 32345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 32355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 32365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 32375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 32385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 32395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null); 32405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 32415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 32425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 32435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 32445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 32455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 32465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 32475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 32485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 32495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 32505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 32515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 32525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 32535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 32545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 32555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 32565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 32574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + sb); 3258ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 32595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3260ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3261ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3262ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 32634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 32644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 32654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 326689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 326789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 32684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 32694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 32704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 327148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 327248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 327348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 327448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov appendAccountFromParameter(qb, uri); 327548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 327648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 327748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 327848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 327948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 32805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 32814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 32824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 328389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 328489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 32854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 32865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + Email.DATA + "="); 32874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhereEscapeString(uri.getLastPathSegment()); 32884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3289ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3290ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3291ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 32925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 32935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 32945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.setProjectionMap(sDistinctDataProjectionMap); 329589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 329689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 32975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 32985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 32995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 33005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 33015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 33025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 33035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 33045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 33055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null); 33065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 33075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 33085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 33095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Email.DATA + " LIKE "); 33101e530df9f7e496dc47f77d4323c89bd413b79b64Dmitri Plotnikov sb.append(DatabaseUtils.sqlEscapeString(filterParam + '%')); 33115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 33125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + sb); 33135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 33145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 33155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 33165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 33175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3318ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 33194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 33204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 332189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 332289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 332389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3324ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3325ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3326ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 332748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 332848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 332948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 333048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov appendAccountFromParameter(qb, uri); 333148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 333248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 333348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 333448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 333548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 333648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 33375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 33384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getRawContactView()); 3339d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 334089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 33414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 33424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 33434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 33445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 33455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 33464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getRawContactView()); 3347d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 334889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 334989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 33504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 33514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 33524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 33535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 33545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 33554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 33564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 335789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 335889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=" + rawContactId); 3359e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3360e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3361e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 3362e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 33634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 33644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 33654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3366e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3367e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3368e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 33694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 33704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 33714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 33724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Data._ID + "=" + ContentUris.parseId(uri)); 33734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 33744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 33754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 3376a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov case DATA_WITH_PRESENCE: { 3377a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView() + " data" + 3378a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 3379a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + AggregatedPresenceColumns.CONTACT_ID + "=" 3380a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContacts.CONTACT_ID + ")" + 3381a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 3382a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 3383a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ")"); 3384a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov qb.setProjectionMap(sDataWithPresenceProjectionMap); 33855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3386a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3387a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3388a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3389a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 33904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3391a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 3392a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 3393a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 3394e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 3395a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3396a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3397e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 3398e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov mOpenHelper.buildPhoneLookupAndContactQuery(qb, number); 3399e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 3400e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 3401e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 3402e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 3403e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 3404a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3405a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3406a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3407ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 340889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(mOpenHelper.getGroupView()); 3409ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 341089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3411ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3412ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3413ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3414ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3415ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 341689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(mOpenHelper.getGroupView()); 3417ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 341889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(Groups._ID + "=" + groupId); 3419ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3420ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3421ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3422ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 342389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(mOpenHelper.getGroupView() + " AS groups"); 3424ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 342589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 342689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 3427ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3428ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3429ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3430b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 34310c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 3432b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 3433b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3434b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3435b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 343631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 3437d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 34382d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 34392d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 34402d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 34412d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 344231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 3443d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 3444d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 344531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 344631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 344731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 344831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 34497581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 34507581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 34517581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 34522d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 345331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 345431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3455eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3456eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 3457eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 345889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3459e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3460e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 3461e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 3462e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final String groupMembershipMimetypeId = Long.toString(mOpenHelper 3463e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 3464ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (mOpenHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3465e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3466e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3467ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (mOpenHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3468e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3469e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3470e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3471eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3472eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3473eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 34745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case PRESENCE: { 3475a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov qb.setTables(Tables.PRESENCE + 3476a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 3477a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON(" + Presence.DATA_ID + "=" + StatusUpdatesColumns.DATA_ID + ")"); 3478373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setProjectionMap(sPresenceProjectionMap); 34795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 34805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 34815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 34825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case PRESENCE_ID: { 3483373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setTables(Tables.PRESENCE); 3484373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setProjectionMap(sPresenceProjectionMap); 3485373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.appendWhere(Presence._ID + "=" + ContentUris.parseId(uri)); 34865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 34875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 34885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 3489c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 3490a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 3491c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3492c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3493c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 3494b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3495b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh(db, contactId, projection); 3496c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3497c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 34981b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 34991b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 35001b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 35011b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 35021b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 35031b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 35041b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 35051b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 35061b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 35071b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 35081b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 35091b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 35101b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 35111b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 35121b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 35131b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 35141b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 35151b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 35161b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 35171b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 35181b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(sContactsInGroupSelect); 35191b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 35201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 35211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 35224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 3523f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 3524c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 35254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 35285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 35315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 35325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 3533038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 3534038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 3535038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 3536038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 35375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 35385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 35394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 35404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 35414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 35434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 35465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 35475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 35485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 35505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 35515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 35525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 35555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 35585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 35595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 35615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 35625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 35635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 35645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 35655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 35665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 35685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 35695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 35705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 35715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 35745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 35755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 35765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 35775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 35785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 35795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 35805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 35845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 35855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 35885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 35895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 35905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 35915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 35925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 35935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 35945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 35955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 35985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 35995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 36015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 36025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 36035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 36045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 36055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 36065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 36075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 36085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 36095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 36105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 36115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 36125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 36135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 36145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 36155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 36195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 36205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 36235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 36265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 36275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 36295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 36305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 36315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 36325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 36335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 36345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 36365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 36375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 36385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 36395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 36425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 36435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 36445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 36455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 36465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 36475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 36485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 36525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 36535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 36565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 36575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 36585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 36595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 36605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 36615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 36625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 36635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 36665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 36675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 36685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 36705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 36715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 36725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 36735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 36745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 36755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 36765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 36775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 36785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 36795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 36805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 36815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 36825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 36835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 36845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 36885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 36895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 36925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 36955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 36965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 36975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 36985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 36995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 37015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 37025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 37045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 37055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 37075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 37085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 37095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 37105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 37115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 37125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 37135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 37145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 37155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 37165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 37185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 37195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 37235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 37245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 37255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 37265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3729ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, String[] projection) { 3730ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov String contactView = mOpenHelper.getContactView(); 3731ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov boolean needsPresence = mOpenHelper.isInProjection(projection, Contacts.PRESENCE_STATUS, 3732ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.PRESENCE_CUSTOM_STATUS); 3733ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (!needsPresence) { 3734ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setTables(contactView); 3735ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 3736ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } else { 3737a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov qb.setTables(contactView + 3738a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 3739a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ") " + 3740a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 3741a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 3742a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ")"); 3743ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setProjectionMap(sContactsWithPresenceProjectionMap); 3744ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 3745ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 3746ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 3747ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 37484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 37494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 37504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 37514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 37524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 37534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 37544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 37554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 37564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 37574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 37584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 37594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 37604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3761e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 3762e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 3763e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 3764e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(accountName)) { 3765e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 3766e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 3767e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 3768e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 3769e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 3770e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 3771e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 3772e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 3773e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3774e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 3775e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 3776e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 3777e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3778e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3779e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 37807e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 3781c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 3782c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 3783c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 3784c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 3785c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 3786c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private String getLimit(Uri url) { 3787c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limitParam = url.getQueryParameter("limit"); 3788c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 3789c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3790c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3791c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 3792c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 3793c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 3794c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 3795c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 3796c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3797c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3798c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 3799c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 3800c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 3801c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3802c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3803c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3804c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 38055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 38065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 38075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 38085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 38095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 38105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 38115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 38125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 38135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 38145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 38155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 38165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 38175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 38195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 38205e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 38215e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 38235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 38245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 38265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 38275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 38295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 38305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 38325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 38335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 383500ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 38364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (mOpenHelper.hasRestrictedAccess()) { 383770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 383870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 38396cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 384070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 384170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 384270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 384370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 38444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (mOpenHelper.hasRestrictedAccess()) { 384570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 384667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 38475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 38485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 3849619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3850619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3851619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3852b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 3853b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 3854b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 3855b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 3856d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 3857b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 3858b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 3859b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3860b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3861b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 3862b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3863b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 3864b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mOpenHelper.getDataView() + 3865b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 3866b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=" + contactId; 3867b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 3868b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, null); 3869d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3870d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3871d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_LOOKUP: 3872d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_LOOKUP_ID: { 3873d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // TODO: optimize lookup when direct id provided 3874d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 3875d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 3876d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String selection = RawContacts.CONTACT_ID + "=" + contactId; 3877d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3878d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 3879d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 3880d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 3881d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 3882d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey outputRawContactsAsVCard(localStream, selection, null); 3883d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 3884d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3885b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3886b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 3887b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("No file at: " + uri); 3888b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3889b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3890b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3891d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 3892d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String VCARD_TYPE_DEFAULT = "default"; 3893d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3894d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 3895d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 3896d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 3897d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 3898d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 3899d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 3900d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 3901d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 3902d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3903d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 3904d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 3905d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3906d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 3907d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 3908d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 3909b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3910d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 3911d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 3912d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 3913d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3914d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 3915d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3916d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3917d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 3918d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 3919d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 3920d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 3921d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 3922d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 3923d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 3924d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 3925d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final VCardComposer composer = new VCardComposer(context, VCARD_TYPE_DEFAULT, false); 3926d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 3927d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3928d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // TODO: enforce the callers security clause is used 3929d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.init(selection, selectionArgs)) 3930d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 3931d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3932d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 3933d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 3934d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 3935d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3936d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3937d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 3938d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3939b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3940bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3941bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov private static Account readAccountFromQueryParams(Uri uri) { 3942bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String name = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 3943bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String type = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 3944bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 3945bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return null; 3946bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 3947bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return new Account(name, type); 3948bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 3949bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3950bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3951619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 39527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 39537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 39547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 3955d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static class RawContactsEntityIterator implements EntityIterator { 39567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 39577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 39587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 39607a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 39617a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 39627a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 39637a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 39647a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 39657a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 39667a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 39677a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 39687a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 39697a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 39707a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 39717a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 39727a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 39737a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 39747a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 39757a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 39767a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 39777a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 39787a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4}; 39797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39807e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] PROJECTION = new String[]{ 39816cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 39826cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 39836cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.SOURCE_ID, 39846cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.VERSION, 39856cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.DIRTY, 39867a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data._ID, 39877a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RES_PACKAGE, 39887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.MIMETYPE, 39897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 39907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 39917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 39927a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 39937a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 39947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 39957a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 39967a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 39977a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 39987a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 39997a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 40007a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 40017a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 40027a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 40037a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 40047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 40057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 40067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 40077a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4, 40087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RAW_CONTACT_ID, 40097a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.IS_PRIMARY, 40103cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar Data.IS_SUPER_PRIMARY, 40117a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA_VERSION, 40127a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana GroupMembership.GROUP_SOURCE_ID, 40137a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC1, 40147a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC2, 40157a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC3, 401694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana RawContacts.SYNC4, 401738446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey RawContacts.DELETED, 4018c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.CONTACT_ID, 4019c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.STARRED}; 4020035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 4021035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 4022035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 4023035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 4024035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 4025035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 4026035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 402767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_RES_PACKAGE = 6; 402867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_MIMETYPE = 7; 402967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA1 = 8; 40307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_RAW_CONTACT_ID = 27; 40317a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_IS_PRIMARY = 28; 40323cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_IS_SUPER_PRIMARY = 29; 40333cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DATA_VERSION = 30; 40343cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_GROUP_SOURCE_ID = 31; 40353cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC1 = 32; 40363cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC2 = 33; 40373cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC3 = 34; 40383cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC4 = 35; 40393cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DELETED = 36; 40403cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_CONTACT_ID = 37; 40413cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_STARRED = 38; 40427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4043d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey public RawContactsEntityIterator(ContactsProvider2 provider, String contactsIdString, Uri uri, 40447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 40457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 40467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final String updatedSortOrder = (sortOrder == null) 40487a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana ? Data.RAW_CONTACT_ID 40497a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana : (Data.RAW_CONTACT_ID + "," + sortOrder); 40507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 40527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 4053226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setTables(Tables.CONTACT_ENTITIES); 40547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 40555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.appendWhere(Data.RAW_CONTACT_ID + "=" + contactsIdString); 40567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40576cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 40586cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 4059035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName)) { 406023c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana if (contactsIdString != null) { 406123c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana qb.appendWhere(" AND "); 406223c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana } 40636cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 4064035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 40656cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 4066035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 4067035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 40687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 40697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana null, null, updatedSortOrder); 40707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 40717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4073038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4074038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4075038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4076038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4077038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4078038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4079038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana 40807e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 40817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 40827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 40837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 40857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 40867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 40897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 40907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 40917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 40947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 40977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 40987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 40997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 41017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 41027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 41047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 41057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 41067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final long rawContactId = c.getLong(COLUMN_RAW_CONTACT_ID); 41077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 41087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 41097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 41106cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 41116cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 41125ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 41136cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 41146cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 41156cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 41167a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC1, c.getString(COLUMN_SYNC1)); 41177a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC2, c.getString(COLUMN_SYNC2)); 41187a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC3, c.getString(COLUMN_SYNC3)); 41197a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC4, c.getString(COLUMN_SYNC4)); 412094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana contactValues.put(RawContacts.DELETED, c.getLong(COLUMN_DELETED)); 412138446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey contactValues.put(RawContacts.CONTACT_ID, c.getLong(COLUMN_CONTACT_ID)); 4122c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey contactValues.put(RawContacts.STARRED, c.getLong(COLUMN_STARRED)); 41237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 41247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 41257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 41267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 41277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana if (rawContactId != c.getLong(COLUMN_RAW_CONTACT_ID)) { 41287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 41297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 413023c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// if (c.isNull(COLUMN_CONTACT_ID)) { 413123c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// continue; 413223c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// } 41337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 41347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 413523c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data._ID, c.getLong(COLUMN_DATA_ID)); 41367a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 41377a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 413823c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_PRIMARY, c.getLong(COLUMN_IS_PRIMARY)); 413923c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_SUPER_PRIMARY, c.getLong(COLUMN_IS_SUPER_PRIMARY)); 41407a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 41419261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 41429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana dataValues.put(GroupMembership.GROUP_SOURCE_ID, 41439261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.getString(COLUMN_GROUP_SOURCE_ID)); 41449261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 41457a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 41467a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana for (int i = 0; i < DATA_KEYS.length; i++) { 41477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 41487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 41497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 41507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 41517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 41527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 41537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 41547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 41557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 41567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 41577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 41587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 41597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 41627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 41637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 41647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 41657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4168226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana /** 4169226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 4170226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 4171226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana */ 4172226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static class GroupsEntityIterator implements EntityIterator { 4173226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private final Cursor mEntityCursor; 4174226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private volatile boolean mIsClosed; 4175226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4176226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final String[] PROJECTION = new String[]{ 4177226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups._ID, 4178226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_NAME, 4179226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_TYPE, 4180226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.SOURCE_ID, 4181226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.DIRTY, 4182226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.VERSION, 4183226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.RES_PACKAGE, 4184226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE, 4185226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE_RES, 41867a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.GROUP_VISIBLE, 41877a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC1, 41887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC2, 41897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC3, 41907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC4, 41917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYSTEM_ID, 419294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.NOTES, 419394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.DELETED}; 4194226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4195226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ID = 0; 4196226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_NAME = 1; 4197226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_TYPE = 2; 4198226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_SOURCE_ID = 3; 4199226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_DIRTY = 4; 4200226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_VERSION = 5; 4201226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_RES_PACKAGE = 6; 4202226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE = 7; 4203226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE_RES = 8; 4204226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_GROUP_VISIBLE = 9; 42057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 10; 42067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 11; 42077a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 12; 42087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 13; 42097a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYSTEM_ID = 14; 42107a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_NOTES = 15; 421194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana private static final int COLUMN_DELETED = 16; 4212226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4213226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 4214226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 4215226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = false; 4216226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4217226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String updatedSortOrder = (sortOrder == null) 4218226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ? Groups._ID 4219226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana : (Groups._ID + "," + sortOrder); 4220226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4221226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 4222226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 422389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(provider.mOpenHelper.getGroupView()); 4224226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setProjectionMap(sGroupsProjectionMap); 4225226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (groupIdString != null) { 4226226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups._ID + "=" + groupIdString); 4227226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4228226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountName = uri.getQueryParameter(Groups.ACCOUNT_NAME); 4229226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountType = uri.getQueryParameter(Groups.ACCOUNT_TYPE); 4230226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!TextUtils.isEmpty(accountName)) { 4231226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups.ACCOUNT_NAME + "=" 4232226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4233226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + Groups.ACCOUNT_TYPE + "=" 4234226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 4235226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4236226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 4237226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana null, null, updatedSortOrder); 4238226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToFirst(); 4239226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4240226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4241226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public void close() { 4242226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4243226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("closing when already closed"); 4244226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4245226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = true; 4246226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.close(); 4247226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4248226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4249226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public boolean hasNext() throws RemoteException { 4250226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4251226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 4252226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4253226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4254226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return !mEntityCursor.isAfterLast(); 4255226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4256226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4257038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4258038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4259038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4260038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4261038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4262038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4263e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4264226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public Entity next() throws RemoteException { 4265226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4266226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 4267226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4268226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!hasNext()) { 4269226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 4270226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4271226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4272226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 4273226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4274226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final long groupId = c.getLong(COLUMN_ID); 4275226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4276226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana // we expect the cursor is already at the row we need to read from 4277226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ContentValues groupValues = new ContentValues(); 4278226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 4279226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 4280226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups._ID, groupId); 4281226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 4282226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 4283226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 4284226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 4285226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 4286226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 4287226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 42887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC1, c.getString(COLUMN_SYNC1)); 42897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC2, c.getString(COLUMN_SYNC2)); 42907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC3, c.getString(COLUMN_SYNC3)); 42917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC4, c.getString(COLUMN_SYNC4)); 42927a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYSTEM_ID, c.getString(COLUMN_SYSTEM_ID)); 429394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana groupValues.put(Groups.DELETED, c.getLong(COLUMN_DELETED)); 42947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.NOTES, c.getString(COLUMN_NOTES)); 4295226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Entity group = new Entity(groupValues); 4296226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4297226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToNext(); 4298226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4299226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return group; 4300226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4301226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4302226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4303a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 43047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 43057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 4306568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 4307568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 43087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 43097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 43105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: 43115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: 43127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 43135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (match == RAW_CONTACTS_ID) { 43147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 43157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 43167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4317d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return new RawContactsEntityIterator(this, contactsIdString, 43187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana uri, selection, selectionArgs, sortOrder); 4319226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS: 4320226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS_ID: 4321226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String idString = null; 4322226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (match == GROUPS_ID) { 4323226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana idString = uri.getPathSegments().get(1); 4324226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4325226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4326226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return new GroupsEntityIterator(this, idString, 4327226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana uri, selection, selectionArgs, sortOrder); 43287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 43297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 43307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 43317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 43327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 43334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 43344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4335a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 43364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4337b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4338b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP: 4339be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 4340b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4341b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4342b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4343b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4344be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4345b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4346b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4347508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4348b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return mOpenHelper.getDataMimeType(ContentUris.parseId(uri)); 434948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 435048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 435148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 435248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 435348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 435448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 435548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 435648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 435748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 435848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 435948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 436048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4361b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4362b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4363b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4364b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4365b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4366b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4367b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4368b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4369c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4370c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4371c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4372c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 437361efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 437461efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 43754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 43764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 43777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 437825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private void setDisplayName(long rawContactId, String displayName, int bestDisplayNameSource) { 43793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 438025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindString(1, displayName); 43813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 438225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindNull(1); 43833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 438425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(2, bestDisplayNameSource); 438525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(3, rawContactId); 438625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 43873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 43883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 438973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 439073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 439173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 439273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 439373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.bindLong(1, rawContactId); 439473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.execute(); 439573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 439673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4397c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4398c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 4399c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 4400c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4401c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4402c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4403653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 4404c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 4405653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 4406653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 4407c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 4408c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4409c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 4410c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4411c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 4412c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 4413c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4414c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4415c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4416653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 4417c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 4418653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 4419653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 4420c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 4421c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4422ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4423f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 4424f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 4425f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4426f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4427f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4428f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); 4429f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (tokens.length == 0) { 4430f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4431f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4432f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4433f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String address = tokens[0].getAddress(); 4434f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int at = address.indexOf('@'); 4435f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (at != -1) { 4436f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov address = address.substring(0, at); 4437f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4438f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4439f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4440f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 4441f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4442f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4443f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4444f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 4445f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4446f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 4447f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 4448f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4449f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4450f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4451f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4452f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 4453f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4454f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4455a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 4456a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 4457a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 4458a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4459a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 4460a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4461a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 4462a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4463a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 4464a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4465a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4466f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4467f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name) { 4468f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name); 4469f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4470f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4471f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4472f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Returns nickname cluster IDs or null. Maintains cache. 4473f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4474f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4475f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SoftReference<String[]> ref; 4476f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4477f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4478f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (mNicknameClusterCache.containsKey(normalizedName)) { 4479f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = mNicknameClusterCache.get(normalizedName); 4480f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (ref == null) { 4481f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return null; 4482f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4483f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = ref.get(); 4484f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4485f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4486f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4487f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (clusters == null) { 4488f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = loadNicknameClusters(normalizedName); 4489f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = clusters == null ? null : new SoftReference<String[]>(clusters); 4490f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4491f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNicknameClusterCache.put(normalizedName, ref); 4492f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4493f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4494f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4495f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4496f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4497f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] loadNicknameClusters(String normalizedName) { 4498f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 4499f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4500f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupQuery.TABLE, NicknameLookupQuery.COLUMNS, 4501f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.NAME + "=?", new String[] { normalizedName }, 4502f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov null, null, null); 4503f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov try { 4504f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int count = cursor.getCount(); 4505f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (count > 0) { 4506f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = new String[count]; 4507f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov for (int i = 0; i < count; i++) { 4508f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.moveToNext(); 4509f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters[i] = cursor.getString(NicknameLookupQuery.CLUSTER); 4510f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4511f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4512f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } finally { 4513f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.close(); 4514f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4515f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4516f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4517f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4518f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 4519f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4520f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 4521f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 4522f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4523f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4524f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4525f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 4526f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 4527f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 4528f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4529f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4530f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4531f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4532f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return ContactsProvider2.this.getCommonNicknameClusters(normalizedName); 4533f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4534f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4535f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4536f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4537f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 4538f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4539f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 4540f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 1, rawContactId); 4541f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 2, dataId); 4542f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 3, lookupType); 4543f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 4, name); 4544f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 4545f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4546f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4547f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4548f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 4549f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4550f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 4551f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupDelete, 1, dataId); 4552f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 4553f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4554f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 45552d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 4556d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4557d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 4558d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4559d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 4560d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 4561d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 4562d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 4563e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 4564d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN(" 4565d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 4566d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 4567d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NICKNAME + "," 4568d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.ORGANIZATION + "))"); 4569e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 4570e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 45715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 4572c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4573c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 4574c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 4575c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4576c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4577a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 4578c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit) { 45795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), limit); 45805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 45825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 45835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String limit) { 4584d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4585d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + NameLookupColumns.RAW_CONTACT_ID + 4586d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 4587d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 4588d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 45895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 4590a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 4591a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 4592a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 4593d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 4594a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.ORGANIZATION + ")"); 45953de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 4596c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limit != null) { 4597c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(" LIMIT ").append(limit); 4598c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4599c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(")"); 4600ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4601ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 46024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 46034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 46044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 46054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 4606b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 4607b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 4608b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 4609b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 4610b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 46114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 46124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 4613b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 4614b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4615b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4616caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 4617caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 4618caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 4619caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 4620df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 4621df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 4622caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 4623caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 4624caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 4625caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 46266f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 4627caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 46286f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 4629caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 46304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 4631