ContactsProvider2.java revision 5e28b3a5e44bf4f2c0980c50a2ab35350fc5f230
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; 21b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 22b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 23b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 24b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkeyimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 26b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 27b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DisplayNameSources; 28b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 29b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 30b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 31b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 32b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NicknameLookupColumns; 33b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 34b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 35b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 36b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 37b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 38b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 39b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 40a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Lists; 41a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Maps; 42a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Sets; 433de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 44b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 45caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 465b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 47c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 48568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 49568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 506ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 5135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 5435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.Entity; 5567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.EntityIterator; 56568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 5867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 593de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.content.SharedPreferences.Editor; 60b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 62ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 63a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 64b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 65b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 68c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 706ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 71d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 72b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 730e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 74d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 753d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 76508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 773de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 783de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.LiveFolders; 793de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.OpenableColumns; 803de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.SyncStateContract; 81b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 823de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 833de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 843de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 853de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 863de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 873de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 8882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 90ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 91ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 95de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 96b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 974097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 9867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 99a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 100a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 101f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Token; 102f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer; 103c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 105d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 106b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 107d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 108d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 109f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport java.lang.ref.SoftReference; 1107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 112b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1130e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 115622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 116b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1170e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 118ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1245b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 125caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 126bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 127bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 128bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 130619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 131619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 132619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1440e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1450e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 146a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1485e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final String TIMES_CONTACED_SORT_COLUMN = "times_contacted_sort"; 1495e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 150d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 1515e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar + TIMES_CONTACED_SORT_COLUMN + " DESC, " 1529b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 153d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 154d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 155d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 156d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 157d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 158d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 167f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 1684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 17246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 1734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1746bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1756bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 176ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 17748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 17848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 17948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 18048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 18148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 18248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 18348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 18448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 185a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1866bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1876bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 188b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 189b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 190b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 19182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 19282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 1931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 19431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 19531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 196eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 197eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 198ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 199ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 200ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 201ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 20235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 203b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 20435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 205c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 206c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 207c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2081b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2091b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2101b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2111b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2121b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 21346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 21446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 21567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private interface ContactsQuery { 2165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final String TABLE = Tables.RAW_CONTACTS; 2179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 21867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2196cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2206cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 2216cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 222ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 223ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2245ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 22567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_NAME = 1; 22667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_TYPE = 2; 22767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 22867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 229d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 230f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 231f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 232f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 23367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 23467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2356cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 237f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 238ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 239ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 240d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 24167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 242d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 243ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private interface DisplayNameQuery { 24667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final String[] COLUMNS = new String[] { 2493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 251f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 252a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka Organization.TITLE, 2533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 0; 2563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 1; 257a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public static final int DATA = 2; 258a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public static final int TITLE = 3; 2593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 26267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 269f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 27088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 27188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 27288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 27388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 27488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 27588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 27688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 277f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 2783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 28014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 284f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 2853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 28714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 288321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 28920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 29020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 291321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 292321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 29320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 29420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 295f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 296f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private interface NicknameLookupQuery { 297f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 298f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 299f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] COLUMNS = new String[] { 300f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.CLUSTER 301f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov }; 302f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 303f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int CLUSTER = 0; 304f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 305f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 30619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 30719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 30819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 30919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 31019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.DELETED 31119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 31219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 31319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 31419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 31519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 31625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private static final HashMap<String, Integer> sDisplayNameSources; 3173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov static { 31825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources = new HashMap<String, Integer>(); 31925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(StructuredName.CONTENT_ITEM_TYPE, 32025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.STRUCTURED_NAME); 321a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sDisplayNameSources.put(Nickname.CONTENT_ITEM_TYPE, 322a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka DisplayNameSources.NICKNAME); 32325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Organization.CONTENT_ITEM_TYPE, 32425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.ORGANIZATION); 32525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Phone.CONTENT_ITEM_TYPE, 32625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.PHONE); 32725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Email.CONTENT_ITEM_TYPE, 32825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.EMAIL); 3293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 33031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 331c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 332df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 333caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 33471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 33571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 33671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 33771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 33871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 33971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 34071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 34171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 34271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 34371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 34471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 34571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 34671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 34771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 348038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 349038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 350e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 3525e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 3535e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentStarredProjectionMap; 3545e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentFrequentProjectionMap; 355f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 356f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final HashMap<String, String> sContactsVCardProjectionMap; 357ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 358d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 35946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** Contains the columns from the raw contacts entity view*/ 36046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final HashMap<String, String> sRawContactsEntityProjectionMap; 3614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3659261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 366e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 367ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 368ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 369ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 370ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 371373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 372b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 373eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 374eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 37582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 37682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 3771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 380c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 381c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 383c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 384ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton /** Precompiled sql statement for incrementing times contacted for a contact */ 385ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton private SQLiteStatement mContactsLastTimeContactedUpdate; 3863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 38725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 38873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** Precompiled sql statement for marking a raw contact as dirty */ 38973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private SQLiteStatement mRawContactDirtyUpdate; 39082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 391a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 392f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 393f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 394a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 395a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 396a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 3970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 398a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 399a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 400f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 401f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 402f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 403f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 4044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 4054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 406a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 407d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 408d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 409d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 4103653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 4113653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 4122d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 4132d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 4143653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 4155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 4165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 4175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 418f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 4195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 420ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 421ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 4225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 4233653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4245ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4255ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 42746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 42846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 42946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 430b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 433ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 43448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 436ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 43848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 442ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 44348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 445ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 446ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 447ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 448ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 44935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 450b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 451b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 45235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 453a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 454b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 455b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 456b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 457b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 459eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 460eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 46182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 46282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 4631f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 464c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 465c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 466c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 467c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 468c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 469c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 470c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4711b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4721b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 4751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 4761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 4771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 4781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 47919a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 48019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 48119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 482038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 483038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 484e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 4864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 4874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 4884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 494f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 4954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 497f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 4983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 4993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 5003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 5013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 5023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 5033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 5043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 5053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 5063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 5073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 5083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 5093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 5103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 5113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 5125e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5135e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5145e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Long.MAX_VALUE + " AS " + TIMES_CONTACED_SORT_COLUMN); 5155e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5165e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5175e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5185e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Contacts.TIMES_CONTACTED + " AS " + TIMES_CONTACED_SORT_COLUMN); 5195e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 520f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap = Maps.newHashMap(); 521f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 522d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 523f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "0 AS " + OpenableColumns.SIZE); 5244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 5264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 5274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 5334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 5344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 5354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 5364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 5374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 5384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 5394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 5404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 5414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 5424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 5434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 5444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 5452815f58f72f109790585931f601a63ddc02536a5Evan Millar 5464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 5474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 5484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 5494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 5554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 5564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 5574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 5584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 5594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 5604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 5614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 5624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 5634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 5644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 5654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 5664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 5674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 5684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 5694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 57382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 5744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 57956d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 587a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 5884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 589a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 59046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana HashMap<String, String> columns; 59146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns = new HashMap<String, String>(); 59246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts._ID, RawContacts._ID); 59346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 59446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 59546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 59646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 59746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.VERSION, RawContacts.VERSION); 59846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 59946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DELETED, RawContacts.DELETED); 60046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 60146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 60246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 60346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 60446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 60546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.MIMETYPE, Data.MIMETYPE); 60646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA1, Data.DATA1); 60746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA2, Data.DATA2); 60846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA3, Data.DATA3); 60946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA4, Data.DATA4); 61046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA5, Data.DATA5); 61146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA6, Data.DATA6); 61246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA7, Data.DATA7); 61346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA8, Data.DATA8); 61446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA9, Data.DATA9); 61546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA10, Data.DATA10); 61646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA11, Data.DATA11); 61746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA12, Data.DATA12); 61846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA13, Data.DATA13); 61946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA14, Data.DATA14); 62046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA15, Data.DATA15); 62146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC1, Data.SYNC1); 62246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC2, Data.SYNC2); 62346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC3, Data.SYNC3); 62446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC4, Data.SYNC4); 62546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 62646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.STARRED, Data.STARRED); 62746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 62846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 62946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 63046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 63146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana sRawContactsEntityProjectionMap = columns; 63246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 6333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 6343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 6353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 6363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 6373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 6383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 6393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 6433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 6453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 6463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 6483296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.PRESENCE, 6493296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 6503296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS, 6513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 6523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 6533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 6553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_LABEL, 6573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_ICON, 6593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 6603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 6625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 6635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 6645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 6655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 6665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 6675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 6685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 6695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 6705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 6715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 6725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 6735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 6745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 6755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 6765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 6775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 6785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 6795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 6805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 6815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 6825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 6835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 6845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 6855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 6865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 6875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 6885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 6895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 6908f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 6915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 6925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 6935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 6945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 6955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 6965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 6975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 698a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 6995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 7005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 7015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 7023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 7033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 7043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 7053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 7063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 7073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 7083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 7103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 7123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 7143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 7153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 7173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 7183296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 7193296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS, 7203296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 7213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 7223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 7243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 7263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 7283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 7293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 730e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 731e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 732e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_ID + " AS " + PhoneLookup._ID); 73356d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 73456d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar Contacts.LOOKUP_KEY + " AS " + PhoneLookup.LOOKUP_KEY); 735e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 736e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + PhoneLookup.DISPLAY_NAME); 737e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 738e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 739e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 740e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 741e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " + PhoneLookup.TIMES_CONTACTED); 742e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 743e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_STARRED + " AS " + PhoneLookup.STARRED); 744e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 745e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 746e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 747e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.PHOTO_ID + " AS " + PhoneLookup.PHOTO_ID); 748e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 749e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " + PhoneLookup.CUSTOM_RINGTONE); 750e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 751e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.HAS_PHONE_NUMBER + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 752e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 753e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 754e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 755e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 756e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 757e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 758e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 759e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 760e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 7619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 762ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 763ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 76489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 765035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 766035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 7679261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 7689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 7699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 77089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 771ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 77267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 773ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 7743cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 77594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 7763cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 77738446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 77889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 77989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 78089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 78189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 782ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 783ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 7846cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 785ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 786ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 787d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 788d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 789ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 790ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 791ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 792d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 793d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 794ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 795f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 796ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 797ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 798b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 799b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 800b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 801b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 8020c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 8030c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 804b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 805b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 806eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 807eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 808eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 809eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 810eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 811eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 812341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 813341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 814341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 815fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 816341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 817341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 818341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 81968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 82068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 82168936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 82268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 82368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 824e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 82568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 82668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 82768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 828eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 829eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 830373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 8314dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 8320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 8330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 83482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 83582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 83682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 83770c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 83870c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 83982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 84082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 84182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 84282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 8430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 8440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 8450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 8460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 8470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 84882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 84919a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 8501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 8511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 8521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 8531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 8541b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 8551b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 8561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 8571b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 8581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 8591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 8601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 8614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 8624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 8633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 8643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey map.put(toField, fromField + " AS " + toField); 8653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 8663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 8673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 8693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 8713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 873653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 8743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 8763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 877a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 878a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 879a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 880a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 881a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 882a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 883a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 884a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 8853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 887653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 888653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 889b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 890653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 891653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 892653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 893653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 8943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 8963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 898e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 899e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 900e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 901e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 902653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 903e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 904e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 905e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 9063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 9103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 9113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 912653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 913f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 91414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 91514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 916653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 917653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 918653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 919653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 920653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 921653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 922653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 923653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 924653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 925653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 926653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 927653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 928653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 929653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 930653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 931653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 932653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 933653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " = " + dataId, null); 934653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 935653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 936f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 937653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 938653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 9393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 94214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 94314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 94414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 9453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 9463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 9473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 9485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 9493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 9513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 9545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long newPrimaryId = findNewPrimaryDataId(db, rawContactId); 9553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (newPrimaryId != -1) { 95614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov setIsPrimary(rawContactId, newPrimaryId, getMimeTypeId()); 9573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected long findNewPrimaryDataId(SQLiteDatabase db, long rawContactId) { 961e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 962e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 9635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Cursor c = queryData(db, rawContactId); 9643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 965e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 96614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 967f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 968e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 969e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 970e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 971e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 9723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 9743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 9753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 976e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return primaryId; 977e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 978e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 979e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 980e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 981e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 982e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 983e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 984e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 9853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected Cursor queryData(SQLiteDatabase db, long rawContactId) { 98814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return db.query(DataDeleteQuery.TABLE, DataDeleteQuery.CONCRETE_COLUMNS, 98914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId + 99014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " AND " + MimetypesColumns.MIMETYPE + "='" + mMimetype + "'", 9913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov null, null, null, null); 9923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 99425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 9953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String bestDisplayName = null; 99625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 99725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov 99867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Cursor c = db.query(DisplayNameQuery.TABLE, DisplayNameQuery.COLUMNS, 9995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId, null, null, null, null); 10003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 10013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov while (c.moveToNext()) { 10023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String mimeType = c.getString(DisplayNameQuery.MIMETYPE); 1003a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1004a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // Display name is at DATA1 in all type. This is ensured in the constructor. 1005a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String name = c.getString(DisplayNameQuery.DATA); 1006a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (TextUtils.isEmpty(name) 1007a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka && Organization.CONTENT_ITEM_TYPE.equals(mimeType)) { 1008a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka name = c.getString(DisplayNameQuery.TITLE); 10093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1010a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka boolean primary = StructuredName.CONTENT_ITEM_TYPE.equals(mimeType) 1011a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || (c.getInt(DisplayNameQuery.IS_PRIMARY) != 0); 10123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 101301911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (name != null) { 101425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov Integer source = sDisplayNameSources.get(mimeType); 101501911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (source != null 101601911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov && (source > bestDisplayNameSource 101701911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov || (source == bestDisplayNameSource && primary))) { 101825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov bestDisplayNameSource = source; 10193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov bestDisplayName = name; 10203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 10253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 10263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 102825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov setDisplayName(rawContactId, bestDisplayName, bestDisplayNameSource); 1029285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1030285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateDisplayName(db, rawContactId); 1031285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 10323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1033a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1034a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1035a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return true; 1036a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1037622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1038622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1039622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 1040622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * as baseline, but augmented with any updates. 1041622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1042622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 1043622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 1044622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 1045622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=" + dataId, 1046622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey null, null, null, null); 1047622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 1048622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 1049622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 1050622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 1051622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.put(key, cursor.getString(i)); 1052622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1053622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1054622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 1055622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 1056622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1057622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 1058622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 1059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 10633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 10653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1070622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 10713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1072622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 10733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1074622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 10753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 10785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1079622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 108014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 108114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 108214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1083f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1084f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 108525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 108614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 108714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 108814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 108914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 109014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1091f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1092622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1093622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1094cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1095622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1096622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 109714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1098f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 109914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1100f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 1101f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1102f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1103f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 110414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 110525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 110614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 110714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 110814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 110914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 111014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 111114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 111214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 111314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 111414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1115f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 111625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 111714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 11183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1121622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 11223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1123622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1124622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1125622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1126622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 11273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1128622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1129622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1130622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1131622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1132622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1133622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1134622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 113567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1136622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 113767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 113867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1139622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1140622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 11418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1142622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1143622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 114467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 114567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 114667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 114767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 114867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 114967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 11508c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1151622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 1152622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(name); 1153622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 1154622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1155622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1156622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1157622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1158622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1159622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1160622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1161622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1162622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1163622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1164622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1165622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1166622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1167622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1168622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1169622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1170622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1171622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1172622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1173622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1174f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1175622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1176622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1177622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1178f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1179622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1180622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1181622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1182622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1183622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1184622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1185622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1186622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1187622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1188622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1189622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1190622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1191622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1192622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1193622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1194622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1195622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1196622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 119767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 119867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 119967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 120067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1201622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1202622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1203622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1204622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1205622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1206622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 120767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 120867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 120967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1210622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1211622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1212622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 12133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 12183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 12203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 12213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 12233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 12243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 12253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 12263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1230622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1231622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1232622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1234622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1235622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1236f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1237622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1238622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1239622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1240f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1241622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1243622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1244622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1245622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1246622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1247622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1248622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1249622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1250622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 12513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1252622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1253622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1254622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1255622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1256622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 12613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 12633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 12643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1268a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1269a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1270a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1271a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1272a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 127325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1274a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1275a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 12763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 127914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1280f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1281a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1282a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1283a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 128414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 128514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1286f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 128714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 128825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1289a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 1290a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 129114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 129214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 129414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1295a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 129614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 129714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 129925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1300a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 130114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 130214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 130314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 130414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 13053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 13063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 13073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 13083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 13093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 13103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 13113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1313a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1314a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1315a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1316a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1317a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 13183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1320e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1321e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1322e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1323e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1324e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1325e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1326e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 13275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 132814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 132914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 133014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 133114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 133225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1333f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 133414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 133514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 133614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 133714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 133814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1339f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 134014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 134114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 134214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 134314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1344f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 134514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1346f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1347f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 134825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 134914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 135014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 135114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 135214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 135314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 135414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 135514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 135614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 135714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1358f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 135925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 136014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1361e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1362e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1363e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1364e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1365e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1366e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1367e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1368e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1369e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1370e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1371e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1372e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1373e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1374e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 137514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 137614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 137714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 137814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 137914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 138014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 138114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 138214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 138314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 138414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 138514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 138614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 138725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1388f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 138914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 139014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 139114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 139214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 139314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1394f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 139514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 139614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 139714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 139814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1399f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 140014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1401f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1402f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 140325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 140414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 140514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 140614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 140714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 140814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 140914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 141014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 141114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 141214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1413f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 141425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 141514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 141614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 141714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 141814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 14193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 14203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 14223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 14233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 14265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 14270b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 14280b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 14290b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 14300b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1431653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14320b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1433653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14340b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1435285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 143625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 14370b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 14380b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 14390b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1440653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1441653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1442653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1443653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1444653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1445f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 144614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 144714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 14480b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 14490b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 14500b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1451653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1452f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1453653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14540b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1455285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 145625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 14570b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 1458f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 14590b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 146014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 146114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 146314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 146414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 146514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 146614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 146814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1470285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 147125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 147214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1473653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1474653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1475653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1476e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1477e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1478e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1479e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1480653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1481653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1482653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1483e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1484653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1485653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1486e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1487653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 14885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1489653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1490e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 1491653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1492653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1493653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=" + dataId, null); 1494e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 14953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 14983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 14993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 15003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 15013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 15023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 15033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 15043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 15053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 15063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 15073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 15083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 15093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1513653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1514653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1515653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1516653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1517653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1518653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1519653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1520653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1521653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 15220be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 15230be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15240be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1525653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1526653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1527653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1528653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1529f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 153014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1531653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1532f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 15330be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15340be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 15350be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 15360be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 15370be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 15380be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 15390be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 15400be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15410be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 15420be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 15430be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 15440be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1545b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 15460be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1547b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 15480be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1549653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1550653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1551653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1552653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1553653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1554653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1555653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1556653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1557653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1558653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1559653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1560653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1561653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1562653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1563653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1564653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1565653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1566653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1567653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1568653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1569653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1570653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1571653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1572653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1573653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId); 1574653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1575653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1576653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1577653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1578a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1579a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1580a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1581a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1582a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1583653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1584653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1585a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1586a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1587a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1588a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1589a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1590a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1591a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1592a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1593a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1594285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1595285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1596285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1597a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1598a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1599a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1600a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1601a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1602f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1603a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1604f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1605a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1606a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1607a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1608a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1609a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1610a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1611a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1612a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1613a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1614a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1615a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1616a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1617a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1618a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1619a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1620a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1621a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1622a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 16233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 162453056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 1625b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 162631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 16274097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1628f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1629f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private HashMap<String, SoftReference<String[]>> mNicknameClusterCache = 1630f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov new HashMap<String, SoftReference<String[]>>(); 1631622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1632622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1633622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1634f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1635a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1636a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 163720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 163820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1639ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 164073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private boolean mImportMode; 164173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1642b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mInsertedRawContacts = Sets.newHashSet(); 1643b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1644b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1645de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 16461a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 16471a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 164881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 164981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 1650a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 165153056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 1652a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1653a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1654a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1655a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 1656a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 165753056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 165853056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 1659a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 16604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 16614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 16624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1663de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 166435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1665de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1666b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1667a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1668b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1669b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper, mAggregationScheduler); 16700e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1671a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1672b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 1673653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1674c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1675653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1676653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1677653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1678653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1679653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1680c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1681653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1682653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1683653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1684653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1685653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1686653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1687653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1688653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1689653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1690653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1691653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1692ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate = db.compileStatement( 1693ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton "UPDATE " + Tables.CONTACTS + 1694ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton " SET " + Contacts.LAST_TIME_CONTACTED + "=? " + 1695ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton "WHERE " + Contacts._ID + "=?"); 1696a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 169725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate = db.compileStatement( 169825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 169925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " SET " + RawContactsColumns.DISPLAY_NAME + "=?," 170025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov + RawContactsColumns.DISPLAY_NAME_SOURCE + "=?" + 170125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 17023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 170373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 170473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + RawContacts.DIRTY + "=1 WHERE " + RawContacts._ID + "=?"); 170573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1706a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate = db.compileStatement( 1707a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.CONTACTS 1708a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1709a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1710a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1711a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1712a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1713a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1714a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1715a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1716a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1717a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 17180a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 17190a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1720a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LIMIT 1)" 1721a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1722e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1723622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Locale locale = Locale.getDefault(); 172428f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 172528f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 172628f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 172728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 1728622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey context.getString(com.android.internal.R.string.common_name_conjunctions), 1729622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey locale); 1730f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 1731622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mPostalSplitter = new PostalSplitter(locale); 17324097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1733f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1734f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1735f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1736f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1737f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1738f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1739f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1740a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert = db.compileStatement( 1741a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1742a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 1748a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1749a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace = db.compileStatement( 1750a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1751a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 17530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1758a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1759a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp = db.compileStatement( 1760a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 17620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 1763a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 17640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 17650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 17660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate = db.compileStatement( 17670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 17690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 17700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 17710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1772a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1773a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete = db.compileStatement( 1774a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1775a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1776a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 17773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 17783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1779e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 17803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 17813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 178267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 178367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 17843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 17853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 178614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 17873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 17883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1789622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1790622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1791a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1792a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 17933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 17943d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1795568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 17963d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1797568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1798c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov verifyAccounts(); 179970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 1800f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1801f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 18021f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 18034f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 18044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1805c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 1806c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1807c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1808c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 1809c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 181031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1811de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1812b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1813b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 181431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 181531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1816285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov /* package */ ContactAggregationScheduler getContactAggregationScheduler() { 1817285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mAggregationScheduler; 1818285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1819285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1820013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1821013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1822013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1823013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 18243d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 18253d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18263d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 18273d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18283d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1829568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1830568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1831568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1832568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1833568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1834568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1835568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1836568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1837568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1838ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1839568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1840568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1841568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1842568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1843568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1844568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1845568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1846568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1847568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1848568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1849ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1850ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1851568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov scheduleContactAggregation(); 1852568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1853568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1854568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1855568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1856568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1857568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1858568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 18593d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1860568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1861568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 18623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18633d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 18643d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 18653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 18663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 18673d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 18683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 18693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18713d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 18723d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1873568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 18740e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 18753d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 187673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = true; 18773d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 18783d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 18790e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(aggregatorEnabled); 18803d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 18813d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 18823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 18833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 188473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } finally { 188573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = false; 18863d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18873d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18883d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1889a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1890a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 1891a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 1892a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 1893a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1894a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1895a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 1896a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1897a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1898a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1899a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1900a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1901a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1902b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 1903a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1904a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1905568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1906568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 1907568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1908568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1909568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1910568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1911568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1912568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 1913ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 1914ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 1915ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 1916ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 1917ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 1918ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1919ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 1920ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 192181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 1922ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1923ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1924568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1925568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1926568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1927568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1928568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1929568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1930568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1931568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1932568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1933568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1934568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1935568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1936568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1937568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1938568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1939568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1940568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 1941568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1942568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1943568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1944568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1945568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1946568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1947568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 1948568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1949568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1950568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1951568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1953285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1954bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1955b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1956b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1957285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 19581ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1959b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1960b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1961b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1962b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 1963285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 1964b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 1965df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 1966285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1967285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1968285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1969285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 1970bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1971b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1972b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1973285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1974b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 19751ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 19761a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 19771a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 1978b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 19791a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 1980b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1981b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1982b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1983bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1984b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1985b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1986b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long rawContactId : mInsertedRawContacts) { 1987b5a4add17815167d20a90645779df34cdf45280dFred Quintana mContactAggregator.insertContact(mDb, rawContactId); 1988285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1989b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1990b5a4add17815167d20a90645779df34cdf45280dFred Quintana String ids; 1991b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 1992b5a4add17815167d20a90645779df34cdf45280dFred Quintana ids = buildIdsString(mUpdatedRawContacts); 1993b5a4add17815167d20a90645779df34cdf45280dFred Quintana mDb.execSQL("UPDATE raw_contacts SET version = version + 1 WHERE _id in " + ids, 1994b5a4add17815167d20a90645779df34cdf45280dFred Quintana new Object[]{}); 1995b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1996b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1997b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 1998b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 1999b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().update(mDb, id, entry.getValue()); 2000b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2001b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2002b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2003b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2004b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2005b5a4add17815167d20a90645779df34cdf45280dFred Quintana private String buildIdsString(HashSet<Long> ids) { 2006b5a4add17815167d20a90645779df34cdf45280dFred Quintana StringBuilder idsBuilder = null; 2007b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2008b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (idsBuilder == null) { 2009b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder = new StringBuilder(); 2010b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append("("); 2011b5a4add17815167d20a90645779df34cdf45280dFred Quintana } else { 2012b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(","); 2013b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2014b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(id); 2015b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2016b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(")"); 2017b5a4add17815167d20a90645779df34cdf45280dFred Quintana return idsBuilder.toString(); 2018285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2019285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2020285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2021cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 202281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 202381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 202481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 202581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 202681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 202781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 202881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2029cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2030568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2031568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected void scheduleContactAggregation() { 2032dee54bb86f3608730f0b9f37d8982a7f6b280a85Dmitri Plotnikov mContactAggregator.schedule(); 2033568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2034568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2035285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 2036285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mInsertedRawContacts.contains(rawContactId); 2037285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2038285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 20393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 20403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 20413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 20423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 20433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 20443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 20463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 20484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2049de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2050bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2051b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "insertInTransaction: " + uri); 2052b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2053f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2054f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2055f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2056f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2057a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2058a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 205935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2060a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 206135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2062b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 206335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 206435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2065d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2066d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 20676bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 20686bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 20696bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 20705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2071f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 2072d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov id = insertRawContact(values, account); 2073f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2074a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2075a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2076a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 20775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 20785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2079f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2080f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2081a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2082a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2083a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2084a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2085f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2086f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2087a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2088a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2089a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2090ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2091ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 20925aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertGroup(uri, values, account, callerIsSyncAdapter); 2093f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2094ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2095ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2096ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2097eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 20985aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 209943880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2100eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2101eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2102eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 210382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 210482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 21051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 21061f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 21071f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2108a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 210981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2110f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2111a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2112a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 21137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 21147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 21157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2117de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2118a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2119a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2120a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2121035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 2122035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 2123035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 2124035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 2125035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 21267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2127035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 2128035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 21296cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME); 21306cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2131035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 2132035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 2133035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 2134035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 2135035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2136035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 2137035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2138035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 2139df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_NAME, account.name); 2140df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_TYPE, account.type); 2141035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2142035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 21437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 21457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2146d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 21476bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 21486bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 21496bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 21506bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2151d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2152de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 21536bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 21546bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 21556bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2156a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2157a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2158a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2159f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 2160a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2161a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2162d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertRawContact(ContentValues values, Account account) { 2163a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 2164d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov overriddenValues.putNull(RawContacts.CONTACT_ID); 2165f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 21667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 21677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 21693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 21703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 21713d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov overriddenValues.put(RawContacts.AGGREGATION_MODE, 21723d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DISABLED); 21733d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 21743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2175023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov long rawContactId = 2176023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, overriddenValues); 2177023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 2178285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2179285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2180285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.add(rawContactId); 2181023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2182a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2183a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2184a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2185a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2186a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2187a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2188a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2189a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2190f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2191a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2192de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2193de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 219467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2195de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 219620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2197de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2198de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2199de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2200b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2201de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2202de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2203508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2204de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2205de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2206de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2207de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2208de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 22094097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2210b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2211de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2212a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2213a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2214a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2215f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2216de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2217a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2218b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2219a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2220a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2221a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2222a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2223a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 22244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 22268e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 22278e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 22288e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 22298e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 22308e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2231b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2232f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 22338e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 22348e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 22358e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 22368e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2237421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 2238f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22398e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 22408e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 22418e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2242b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2243f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 22448e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 22458e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 22468e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2247f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22488e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2249f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2250c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 2251b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 22528e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2253f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22548e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2255f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2256f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2257f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2258a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 22595ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 22609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 22619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 22625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 22639261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 22649261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 22659261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 22669261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 22679261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 22685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId) { 22699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Account account = null; 22706cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts._ID + "=" 22715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId, null, null, null, null); 22729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 22739261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 227467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountName = c.getString(ContactsQuery.ACCOUNT_NAME); 227567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountType = c.getString(ContactsQuery.ACCOUNT_TYPE); 22769261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 22779261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana account = new Account(accountName, accountType); 22789261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22799261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 22819261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 22829261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 22849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 22859261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "has a sourceid the the contact must be associate with " 22869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 22879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 22899261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 22905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 22916cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 22929261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2293df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 22949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 22959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 22969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return c.getLong(0); 22979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 22989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2299df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2300df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 23019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 23029261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 23039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 23049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 23059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 23069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return groupId; 23089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23099261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 23109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 23119261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23129261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23139261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 23149261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 231520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 231620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2317f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 231820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 231920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2320de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2321de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 232214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2323de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2324de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 232514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 232614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2327a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2328a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2329f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 233088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 2331a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2332a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2333a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 233488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 233520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 233620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2337de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 233820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 233920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 234020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 234120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 234220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 234388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 234488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 234588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 234620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2347f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 234888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 234988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 235014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=" + dataId, null, 235114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov null); 2352f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 235320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 235420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 235520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 235620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 235720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 235814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 235920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 236020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 236120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 236220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 236320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 236420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 236520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 236620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 236720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 23687a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 236920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 237020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 237120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2372a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2373a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 23748e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2375a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2376a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2377a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 23788e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 237920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 238020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 238120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 238220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 238320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 238420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2385ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2386ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2387b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, Account account, 2388b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov boolean callerIsSyncAdapter) { 2389ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 2390ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 2391ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 2392ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2393ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2394ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 239567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.RES_PACKAGE); 239667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 2397b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov overriddenValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 239867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 239967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.remove(Groups.RES_PACKAGE); 2400ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2401f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 240273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov overriddenValues.put(Groups.DIRTY, 1); 240373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 240473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2405ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey long result = mDb.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 2406ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 24071a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (overriddenValues.containsKey(Groups.GROUP_VISIBLE)) { 24081a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2409ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2410ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2411ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2412ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2413ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 24145aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2415e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 24165aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 24171a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 24181a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2419e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 24201a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 2421e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2422e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2423e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2424ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 242582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 24261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 242782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 242882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 24290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 24304dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 24314dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 24320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 243382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 24344dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 24354dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 24364dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 24374dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 24381f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2440dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 2441dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 244282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 2443f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 2444dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 2445dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 2446dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2447f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "="); 2448f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(dataId); 24491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 2450dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 2451dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 24520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 24530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 24540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 24550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2456dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 2457dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 2458dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2459dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 2460f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2461f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 2462f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 2463f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 2464f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2465f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 2466f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 2467f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (") 2468f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2469f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(",") 2470f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2471f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(")" + " AND " + Data.DATA1 + "="); 2472f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2473f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ((" + DataColumns.MIMETYPE_ID + "=") 2474f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2475f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2476f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol); 2477dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2478f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2479f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2480dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2481f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=") 2482f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2483f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append("))"); 2484dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 2485f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=") 2486f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2487f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2488f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol) 2489f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.DATA + "="); 2490f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2491dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2492f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2493f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2494dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2495dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 24961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 249782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 2498f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=") 249982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .append(values.getAsLong(StatusUpdates.DATA_ID)); 2500dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 250170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 2502f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 250370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 25041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 25051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2506de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 2507c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov mSb.toString(), null, null, null, 2508c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 25091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 251067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 25115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2512e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 25131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 25141f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 25151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 25161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 251831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 251931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 252031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 25211f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25221f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 252382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2524a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2525a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2526a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2527a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2528a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2529a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2530a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 253182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2532a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2533a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 253482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 253582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 253682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 253782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 253882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2539a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 254082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 254182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 25421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2543a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2544a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2545a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2546e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 25470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 254882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 254982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 25500a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 25510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 25520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 25530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 25540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 25550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 25560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 25570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 25580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 25590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 25600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 25610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2562a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 2563a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 2564a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 256582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 256682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 2567a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 2568a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 25690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 3, status); 25700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 4, resPackage); 25710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 5, iconResource); 25720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 6, labelResource); 2573a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 2574a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 2575a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2576a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 2577a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 25780a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 2, status); 25790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 3, resPackage); 25800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 4, iconResource); 25810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 5, labelResource); 2582a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 2583a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 2584a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 25850a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 2586a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 25870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 2, status); 2588a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 25890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 4, status); 2590a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 25910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 25920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 1, resPackage); 25930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 2, iconResource); 25940a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 3, labelResource); 25950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 25960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 2597a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2598e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2599e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2600bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2601a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2602a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 2603a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 2604a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 2605a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2606a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2607a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 26081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 26091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 26104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2611de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2612bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2613b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2614b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2615b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2616f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2617f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2618508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2619508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 262035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2621b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 262235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2623b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2624b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2625b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2626b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2627b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2628b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2629cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2630cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2631cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2632cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2633cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2634d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2635d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2636cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 26376bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 26386bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 26392e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 26402e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 26412e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 26422e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 26432e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 26442e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 26452e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26462e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 26472e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 26482e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 26492e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 26512971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 26522971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 26532971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2654e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 26552971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 26562971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 26572971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2658f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana numDeletes += deleteRawContact(rawContactId, callerIsSyncAdapter); 26592971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26602971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 26612971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 26622971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26632971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 26642971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26652971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 26665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 26672971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2668f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteRawContact(rawContactId, callerIsSyncAdapter); 2669508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2670508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 267120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2672f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2673944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2674f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 267520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 267620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 267748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 267848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 267948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 268048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2681508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2682f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2683f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteData(Data._ID + "=" + dataId, null, callerIsSyncAdapter); 2684ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2685ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2686ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2687f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 26885aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 26892971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26902971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 26912971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 26922971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 26932971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2694e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 26952971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 26962971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 26975aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 26982971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26992971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 27002971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 27012971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 270281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2703f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 270481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 27052971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2706508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2707508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2708eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 270943880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 27105aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteSettings(uri, selection, selectionArgs); 2711eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2712eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 271382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 27140a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 27151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 27161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 271781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 271881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 27193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 272081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2721508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 27224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 272446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static boolean readBooleanQueryParameter(Uri uri, String name, boolean defaultValue) { 27252971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final String flag = uri.getQueryParameter(name); 27262971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return flag == null 27272971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana ? defaultValue 27282971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana : (!"false".equals(flag.toLowerCase()) && !"0".equals(flag.toLowerCase())); 272994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 273094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 27315aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 2732b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 273394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2734de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 273594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 273694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 273794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 273894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2739f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2740de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 274194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 274294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 274394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2744f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2745de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 274694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 274794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 27481a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 274994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 275094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 275194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 27525aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2753e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 27541a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2755e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2756e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2757e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2758cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 2759cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2760cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null); 2761cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2762cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2763cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2764cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 2765cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2766cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2767cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2768cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2769cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2770cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2771cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2772cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2773f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana public int deleteRawContact(long rawContactId, boolean callerIsSyncAdapter) { 2774f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 277514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2776de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 277733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2778b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 2779cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 278033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 278133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 278233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 27830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 27840a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO delete from both tables: presence and status_updates 27850a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 27860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 27870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2788cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 278981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 279081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 2791cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 2792cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 2793cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2794cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2795cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2796cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2797cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 2798cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2799cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 28004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2801de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2802de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 2803bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2804b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2805b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2806b5a4add17815167d20a90645779df34cdf45280dFred Quintana 280735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 280800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 280900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 2810b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 2811b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 2812b5a4add17815167d20a90645779df34cdf45280dFred Quintana Object data = values.get(ContactsContract.SyncStateColumns.DATA); 2813b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 2814b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 2815b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2816b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2817f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2818f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 281900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 282035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2821b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2822b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 2823b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2824b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 2825b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 2826b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2827b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2828b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2829b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2830b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 2831b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 283235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2833d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 28348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 283500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 283600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 283700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2838d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 28398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 2840c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2841c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2842c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 28432e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 28442e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 28452e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 28462e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 28472e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 28482e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 28492e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 28502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 28512e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 28528c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 28532e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 28542e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 28552e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 28567d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 28577d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 28587d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 28597d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 28607d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 28617d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 28627d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 28637d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 28647d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 28657d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 286620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2867944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2868f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 286981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2870f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 287181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 287220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 287320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2874c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 287548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 287648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 287748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 287848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2879f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 288081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2881f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 288281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 288300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 288400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 28857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 28865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 28875ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 28884529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 28897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 28907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 28917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 28925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 289333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 28944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 28954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=" + rawContactId 28964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 28974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 289827f039b535f98c1cb1a31207047003235ddaed15Dmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=" + rawContactId, null); 28994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 29007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 29017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 29027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2903ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 29045aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 2905f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 290681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2907f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 290881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2909ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2910ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2911ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2912ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2913ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 291473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String selectionWithId = (Groups._ID + "=" + groupId + " ") 291573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 29165aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 29175aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 291881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2919f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 292081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2921ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2922ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2923ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2924127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 2925de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 2926b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2927b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2928b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2929eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 29305aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateSettings(uri, values, selection, selectionArgs); 293143880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2932eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2933eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2934eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 293581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 293681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2937f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 293881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 293900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 294000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 294100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 29424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 29434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 29445aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 2945f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 294673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 294773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 2948f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 294973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 295073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 295173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 295273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 295373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 295473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 295573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 295673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2957ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 29581a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 29591a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 296094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 29616ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 29626ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 29636ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi final long groupId = ContentUris.parseId(uri); 29646ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 29656ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Groups.ACCOUNT_TYPE}, Groups._ID + "=" + groupId, null, null, 29666ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 29676ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 29686ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 29696ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 29706ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 29716ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 29726ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 29736ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 29746ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 29756ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 29766ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 29776ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 29786ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 29796ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 29806ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 29816ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 29826ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 29836ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 298494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 298594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 298694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2987b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 2988b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 2989e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 29901a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 29911a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2992e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2993e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2994e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2995e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 29964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 29974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 29984529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 29994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 30004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 300173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 30024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3003b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 300451bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 30054529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 30064529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 30074529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 30084529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 30094529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 30104529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 30114529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 30124529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 30134529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 30144529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 30154529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 30164529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 30174529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 30184529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 30194529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 302019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final String selection = RawContacts._ID + " = " + rawContactId; 302119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 302219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 302319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 302419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 302519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 302619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka null, null, null, null); 302719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 302819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 302919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 303019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 303119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 303219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 303319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 303419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 303519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 303619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 303719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int count = mDb.update(Tables.RAW_CONTACTS, values, selection, null); 30385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3039433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 30404529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3041433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3042285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 3043285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateLookupKey(mDb, rawContactId); 3044285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 304519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 304619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 304719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka mInsertedRawContacts.add(rawContactId); 304819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 30495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 305133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 305233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3053321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3054f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 305520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 305620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 305720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 30585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 305920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 306020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 306120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 306220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 306320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3064b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 306520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 306620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 306770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 306870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 306920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 307020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 307120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 307270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 307320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 307470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 307520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 307670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 307720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 307870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 307920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 308020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3081653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 308220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3083653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3084653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 308514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 3086653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 3087653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 3088f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 308920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3090653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 3091653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 309220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 309320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3094653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 309520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 309620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3097f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 3098653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 3099653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 3100321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3101653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 310214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 3103a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3104f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana rowHandler.update(mDb, values, c, callerIsSyncAdapter); 31058e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 3106a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 3107a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 3108a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 31098e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 3110653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 3111321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3112321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 31138c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 31148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 31158c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 3116b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 31178c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 31188c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 31198c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 31208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 31218c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 31228c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 31238c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 31248c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 31258c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 31268c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 31278c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 31288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31298c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 31308c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 31318c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31328c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 3133d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 31348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3135b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3136d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3137b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 3138d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3139b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 3140d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3141b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3142d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3143b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3144d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 3145d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3146d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 31478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 3148d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 3149d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3150d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 31518c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 3152c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 31538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3154c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 3155c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 31568c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=" + contactId, null); 31578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31588c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 31598c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 31608c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3161b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 31628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3163b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 31648c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3165b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 31668c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3167b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 31688c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3169b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 31708c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 31718c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31728c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=" + contactId, null); 3173f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3174d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3175ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton public void updateContactLastContactedTime(long contactId, long lastTimeContacted) { 3176ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 3177ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.bindLong(2, contactId); 3178ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.execute(); 3179d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3180d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3181127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 3182127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 31830c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 31840c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 318580c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 31860c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 31870c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 31880c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 31890c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 31900c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 31910c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 31920c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 3193b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3194127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 31950c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 31960c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 31970c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=" + rawContactId1 + " AND " 31980c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=" + rawContactId2, null); 31990c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 32006bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 32016bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 32020c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 32030c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 32040c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 32050c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 3206127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 3207127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3208dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 3209dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 3210dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 3211b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 32120c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 32130c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 3214b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId2 = mDbHelper.getContactId(rawContactId2); 32150c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 3216127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3217127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 3218127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 3219127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3220b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3221b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 322270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 3223b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 322470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (mDb == null) return; 322570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 322670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong Set<Account> validAccounts = Sets.newHashSet(); 322770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accounts) { 322870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong validAccounts.add(new Account(account.name, account.type)); 322970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 323070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong ArrayList<Account> accountsToDelete = new ArrayList<Account>(); 323170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 323270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 323370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 323448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 32355f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana for (String table : new String[]{Tables.RAW_CONTACTS, Tables.GROUPS, Tables.SETTINGS}) { 32365f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // Find all the accounts the contacts DB knows about, mark the ones that aren't 32375f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // in the valid set for deletion. 32385f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Cursor c = mDb.rawQuery("SELECT DISTINCT account_name, account_type from " 32395f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + table, null); 32405f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana while (c.moveToNext()) { 32415f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (c.getString(0) != null && c.getString(1) != null) { 32425f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Account currAccount = new Account(c.getString(0), c.getString(1)); 32435f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (!validAccounts.contains(currAccount)) { 32445f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana accountsToDelete.add(currAccount); 32455f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana } 324670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 324770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 32485f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana c.close(); 324970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 325070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 325170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 32525f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 325370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong String[] params = new String[]{account.name, account.type}; 325470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.GROUPS 325570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 325670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.PRESENCE 325770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (SELECT " 325870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS 325970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?)", params); 326070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.RAW_CONTACTS 326170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 32625f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana mDb.execSQL("DELETE FROM " + Tables.SETTINGS 32635f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + " WHERE account_name = ? AND account_type = ?", params); 326470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3265b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 326670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 326770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 326870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 326970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 327070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3271619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3272619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3273622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 3274622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 327567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 327667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 327767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 327867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 327967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 328067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 328167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 328267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 328367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 328467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 328567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 328667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 3287dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 3288622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 3289dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 3290dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 3291622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3292622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3293dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 3294622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3295622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 32964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 32974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 32984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 3299bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3300bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3301bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 33020b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 3303b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 330435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3305d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 33061f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3307c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3308c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3309619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3310619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3311a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 33124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 331335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3314b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 331535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 331635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3317d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3318763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3319619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3320619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3321619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3322d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 33234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3324763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 33254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + contactId); 33266bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 33276bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 33286bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 33295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 33305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 33315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 33325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 33335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 33345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 33355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 33375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 33385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 33395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3340763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 33415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=" + contactId + " AND " + 33425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.LOOKUP_KEY + "="); 33435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhereEscapeString(lookupKey); 33445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, selectionArgs, sortOrder, 33455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 33465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 33475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 33485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 33505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 33515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3353763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 33545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 33555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 33565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3358f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 3359f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 3360f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 3361763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 3362f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 3363f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 3364f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 3365f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 3366f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 3367ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3368763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3369ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 33704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 33714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3372e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 33735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 33744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sb.toString()); 3375ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3376ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3377ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3378ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3379ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3380ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 33814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3382ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3383d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 33844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 33854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3386e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 33875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 33884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 33894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 33904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3391763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3392ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 33935e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 33945e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 33955e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 33965e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar starredProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 33975e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar frequentProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 33985e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 33995e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 34004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 34014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 34024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3403d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 34045e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 34055e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 34064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3407d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3408d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3409d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3410763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 34114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 34124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3413d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 34145e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 34155e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 3416d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3417d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 34184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3419d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3420d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3421d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3422d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 34234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 34244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3425d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3426d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3427d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3428d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3429d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3430d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3431ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3432763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3433b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 343471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 34354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3436b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3437b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3438b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3439b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3440d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 34414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 344282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 34434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 34446bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 34456bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 344600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3447ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 34483653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 344982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 34503653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 34513653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 34523653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 34533653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 34543653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 34554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 345682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 345789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 34582815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 34592815f58f72f109790585931f601a63ddc02536a5Evan Millar } 34602815f58f72f109790585931f601a63ddc02536a5Evan Millar 346148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 346282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 346348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 346448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 346548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 346648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 346748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3468ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 346982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 347089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3471ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 34724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 34734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 34745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 34755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 34765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 34775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 34785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 34795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 348020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null, false); 34815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 34825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 34835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 34845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 34855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 34865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 34875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 34885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 34895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 34905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 34915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 34925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 34935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 34945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 34955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 34965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 34975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 34984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + sb); 3499ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 35005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3501a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3502a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3503a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 3504ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3505ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3506ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 35074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 350882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 350989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 35104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 35114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 35124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 351348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 351482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 351548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 351648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 351748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 351848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 351948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 35205e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 352182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 352289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 35234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 35245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + Email.DATA + "="); 35254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhereEscapeString(uri.getLastPathSegment()); 35264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3527ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3528ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3529ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 35305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 353182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 353289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 35335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 35345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 35355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 35365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 35375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 353820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 353920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 354020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 354120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 354220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null, false); 354320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(" OR "); 354420938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 35455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 35475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Email.DATA + " LIKE "); 35481e530df9f7e496dc47f77d4323c89bd413b79b64Dmitri Plotnikov sb.append(DatabaseUtils.sqlEscapeString(filterParam + '%')); 35495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 35505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + sb); 35515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 3553a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3554a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3555a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 35565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 35575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3559ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 356082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 356189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 356289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3563ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3564ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3565ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 356648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 356782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 356848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 356948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 357048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 357148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 357248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 357348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 35745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 3575763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 35764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 35774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 35805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 3581763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 358289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 35834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 35844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 35875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 358882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 358989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=" + rawContactId); 3590e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3591e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3592e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 3593e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 359482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3595e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3596e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3597e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 35984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 359982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 360082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + ContentUris.parseId(uri)); 3601a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3602a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3603a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3604a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 36054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3606a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 3607a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 3608a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 3609e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 3610a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3611a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3612e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 3613b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 3614e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 3615e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 3616e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 3617e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 3618e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 3619a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3620a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3621a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3622ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 3623b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3624ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 362589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3626ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3627ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3628ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3629ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3630ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 3631b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3632ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 363389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(Groups._ID + "=" + groupId); 3634ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3635ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3636ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3637ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 3638b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 3639ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 364089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 364189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 3642ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3643ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3644ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3645b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 36460c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 3647b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 3648b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3649b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3650b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 365131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 3652d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 36532d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 36542d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 36552d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 36562d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 365731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 3658d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 3659d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 366031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 366131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 366231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 366331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3664763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 36657581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 36667581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 36672d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 366831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 366931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3670eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3671eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 3672eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 367389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3674e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3675e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 3676e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 3677b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 3678e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 367982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3680b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3681e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3682e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 368382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3684b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3685e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3686e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3687e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3688eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3689eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3690eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 369182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 36920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 36935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 36945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 36955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 369682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 36970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 36980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=" + ContentUris.parseId(uri)); 36995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 37005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 37015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 3702c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 3703a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 3704c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3705c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3706c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 3707b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3708b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh(db, contactId, projection); 3709c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3710c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 37111b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 3712b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37131b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 37141b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37151b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37161b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 3717b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37181b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 37191b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 37201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 3723b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 37251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 37261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 3729b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 373171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 37321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 37331b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 373546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 373646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 373746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 373846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 373946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 374046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 374146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 374246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 374346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 374446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 374546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 374646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 37474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 3748f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 3749c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 37504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 37525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 37535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 37565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 37575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 3758038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 3759038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 3760038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 3761038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 37625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 37635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 37644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 37654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 37664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 37684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 37705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 37715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 37725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 37735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 37755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 37765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 37775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 37805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 37835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 37845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 37865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 37875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 37885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 37895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 37905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 37915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 37935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 37945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 37955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 37965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 37995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 38005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 38015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 38045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 38055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 38095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 38105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 38135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 38145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 38155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 38185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 38195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 38205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 38235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 38245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 38265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 38275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 38285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 38295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 38305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 38315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 38325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 38335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 38345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 38375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 38385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 38395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 38405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 38445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 38455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 38485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 38515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 38525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 38545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 38555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 38565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 38575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 38585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 38595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 38615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 38625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 38635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 38645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 38675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 38685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 38695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 38725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 38735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 38775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 38785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 38815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 38825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 38835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 38865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 38875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 38885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 38915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 38925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 38935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 38955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 38965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 38975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 38985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 38995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 39005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 39015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 39025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 39035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 39045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 39065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 39075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 39085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 39095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 39135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 39145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 39175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 39205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 39215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 39225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 39235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 39245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 39265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 39275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 39295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 39305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 39325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 39335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 39355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 39365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 39375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 39385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 39395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 39405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 39415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 39435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 39445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 39485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 39495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 39505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 39515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3954763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 3955763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 395682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 3957763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 3958763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 3959763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 3960763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 3961d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 3962763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 3963763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 3964b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 396582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 396682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 396782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 396882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 3969b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 397082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 397182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 397282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 397382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 397482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 39753296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 39763296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 3977a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 39783296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 397982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 398082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 398182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 398282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 3983ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 3984763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 3985763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 3986763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 3987763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 3988763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 3989763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 3990d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 3991763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 3992763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 3993763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 3994763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 3995763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 3996763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 3997763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 399846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 399946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana // Note: currently, "export only" equals to "restricted", but may not in the future. 400046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana boolean excludeRestrictedData = readBooleanQueryParameter(uri, 400146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.FOR_EXPORT_ONLY, false); 400246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 400346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String requestingPackage = uri.getQueryParameter( 400446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 400546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana if (requestingPackage != null) { 400646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana excludeRestrictedData = excludeRestrictedData 400746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 400846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 400946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 401046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setProjectionMap(sRawContactsEntityProjectionMap); 401146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 401246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 401346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 401482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 401582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 401682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4017d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa // Note: currently, "export only" equals to "restricted", but may not in the future. 4018763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = readBooleanQueryParameter(uri, 4019d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa Data.FOR_EXPORT_ONLY, false); 4020763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4021763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 4022763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4023763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4024763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar excludeRestrictedData = excludeRestrictedData 4025d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4026763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4027763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4028763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getDataView(excludeRestrictedData)); 402982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 403082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 40313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated presence when requested 4032b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 403382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 40343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 403582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 403682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 403782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 40383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated status updates when requested 4039b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 404082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 404182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 404282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 404382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 404482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 40453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 40463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 404782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 40483296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 4049ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 40503296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 40513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual presence when requested 40523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 40533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 40543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdates.DATA_ID + "=" 40553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 40563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 40573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 40583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual status updates when requested 40593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, 40603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS, 40613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_RES_PACKAGE, 40623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_ICON, 40633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_LABEL, 40643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_TIMESTAMP)) { 40653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 40663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 40673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 40683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 40693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 407082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 407182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 407282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 4073ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 4074ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 40750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 40760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 40770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4078b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 40790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 40800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4081b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 40820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 40830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 40840a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 40850a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 40860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4087b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 40880a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 40890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 40900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 40910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 40920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 40930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 40940a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 40950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 40960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 40970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setTables(sb.toString()); 40980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 40990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 41000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 41014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 41024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 41034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 41044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 41054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 41064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 41074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 41084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 41094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 41104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 41114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 41124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 41134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4114e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 4115e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 4116e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 4117e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(accountName)) { 4118e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 4119e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4120e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 4121e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 4122e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 4123e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 4124e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 4125e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 4126e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4127e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 4128e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 4129e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 4130e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4131e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4132e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 41337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 4134c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 4135c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 4136c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 4137c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 4138c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 4139c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private String getLimit(Uri url) { 4140c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limitParam = url.getQueryParameter("limit"); 4141c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 4142c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4143c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4144c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 4145c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 4146c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 4147c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 4148c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4149c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4150c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4151c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 4152c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 4153c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4154c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4155c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4156c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4157c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 41585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 41595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 41605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 41615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 41625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 41635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 41645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 41655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 41665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 41675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 41685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 41695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 41705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 41725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 41735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 41745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 41765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 41775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 41795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 41805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 41825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 41835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 41855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 41865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 418800ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 4189d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 419070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 419170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 41926cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 419370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 419470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 419570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 419670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 4197d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 419870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 419967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 42005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 42015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 4202619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4203619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4204619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4205b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 4206b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 4207b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 4208b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 4209d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 4210b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 4211b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 4212b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4213b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4214b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 4215b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4216b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 4217b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 4218b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 4219b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=" + contactId; 4220b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4221b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, null); 4222d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4223d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4224f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 4225d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 4226d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 422714b8a1243ab5c043b35e47527ca1c962064f3771Daisuke Miyakawa final String selection = Contacts._ID + "=" + contactId; 4228d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4229d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 4230d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 4231d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 4232d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 4233d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey outputRawContactsAsVCard(localStream, selection, null); 4234d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 4235d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4236b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4237b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 4238b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("No file at: " + uri); 4239b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4240b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4241b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4242d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 4243d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String VCARD_TYPE_DEFAULT = "default"; 4244d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4245d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4246d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 4247d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 4248d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4249d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 4250d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 4251d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 4252d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 4253d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4254d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 4255d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 4256d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4257d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 4258d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 4259d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 4260b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4261d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 4262d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 4263d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 4264d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4265d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 4266d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4267d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4268d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4269d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 4270d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 4271d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 4272d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4273d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 4274d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 4275d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 4276d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final VCardComposer composer = new VCardComposer(context, VCARD_TYPE_DEFAULT, false); 4277d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 4278d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4279f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 4280d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.init(selection, selectionArgs)) 4281d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 4282d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4283d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 4284d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 4285d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 4286d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4287d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4288d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 4289d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4290b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4291bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4292bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov private static Account readAccountFromQueryParams(Uri uri) { 4293bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String name = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 4294bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String type = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 4295bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 4296bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return null; 4297bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 4298bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return new Account(name, type); 4299bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 4300bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4301bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4302619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 43037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 43047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 43057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 4306d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static class RawContactsEntityIterator implements EntityIterator { 43077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 43087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 43097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 43107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 43117a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 43127a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 43137a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 43147a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 43157a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 43167a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 43177a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 43187a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 43197a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 43207a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 43217a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 43227a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 43237a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 43247a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 43257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 43267a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 43277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 43287a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 43297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4}; 43307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 433146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana public static final String[] PROJECTION = new String[]{ 43326cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 43336cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 43346cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.SOURCE_ID, 43356cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.VERSION, 43366cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.DIRTY, 433746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana RawContacts.Entity.DATA_ID, 43387a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RES_PACKAGE, 43397a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.MIMETYPE, 43407a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 43417a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 43427a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 43437a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 43447a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 43457a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 43467a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 43477a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 43487a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 43497a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 43507a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 43517a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 43527a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 43537a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 43547a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 43557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 43567a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 43577a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 43587a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4, 435946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana RawContacts._ID, 43607a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.IS_PRIMARY, 43613cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar Data.IS_SUPER_PRIMARY, 43627a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA_VERSION, 43637a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana GroupMembership.GROUP_SOURCE_ID, 43647a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC1, 43657a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC2, 43667a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC3, 436794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana RawContacts.SYNC4, 436838446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey RawContacts.DELETED, 4369c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.CONTACT_ID, 4370c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.STARRED}; 4371035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 4372035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 4373035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 4374035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 4375035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 4376035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 4377035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 437867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_RES_PACKAGE = 6; 437967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_MIMETYPE = 7; 438067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA1 = 8; 43817a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_RAW_CONTACT_ID = 27; 43827a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_IS_PRIMARY = 28; 43833cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_IS_SUPER_PRIMARY = 29; 43843cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DATA_VERSION = 30; 43853cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_GROUP_SOURCE_ID = 31; 43863cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC1 = 32; 43873cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC2 = 33; 43883cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC3 = 34; 43893cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC4 = 35; 43903cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DELETED = 36; 43913cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_CONTACT_ID = 37; 43923cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_STARRED = 38; 43937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 439446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana public RawContactsEntityIterator(ContactsProvider2 provider, Uri entityUri, 439546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String contactsIdString, 439646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String selection, String[] selectionArgs, String sortOrder) { 43977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 439846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Uri uri; 43997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 440046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = Uri.withAppendedPath(RawContacts.CONTENT_URI, contactsIdString); 440146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = Uri.withAppendedPath(uri, RawContacts.Entity.CONTENT_DIRECTORY); 440246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } else { 440346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = ContactsContract.RawContactsEntity.CONTENT_URI; 4404035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 440546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana final Uri.Builder builder = uri.buildUpon(); 440646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String query = entityUri.getQuery(); 440746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana builder.encodedQuery(query); 440846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana mEntityCursor = provider.query(builder.build(), 440946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana PROJECTION, selection, selectionArgs, sortOrder); 44107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 44117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4413038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4414038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4415038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4416038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4417038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4418038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4419038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana 44207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 44217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 44227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 44237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 44257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 44267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 44297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 44307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 44317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 44347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 44377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 44387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 44397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 44417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 44427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 44457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44467a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final long rawContactId = c.getLong(COLUMN_RAW_CONTACT_ID); 44477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 44497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 44506cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 44516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 44525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 44536cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 44546cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 44556cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 44567a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC1, c.getString(COLUMN_SYNC1)); 44577a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC2, c.getString(COLUMN_SYNC2)); 44587a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC3, c.getString(COLUMN_SYNC3)); 44597a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC4, c.getString(COLUMN_SYNC4)); 446094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana contactValues.put(RawContacts.DELETED, c.getLong(COLUMN_DELETED)); 446138446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey contactValues.put(RawContacts.CONTACT_ID, c.getLong(COLUMN_CONTACT_ID)); 4462c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey contactValues.put(RawContacts.STARRED, c.getLong(COLUMN_STARRED)); 44637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 44647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 44667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 44677a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana if (rawContactId != c.getLong(COLUMN_RAW_CONTACT_ID)) { 44687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 44697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 447023c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// if (c.isNull(COLUMN_CONTACT_ID)) { 447123c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// continue; 447223c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// } 44737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 44747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 447523c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data._ID, c.getLong(COLUMN_DATA_ID)); 44767a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 44777a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 447823c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_PRIMARY, c.getLong(COLUMN_IS_PRIMARY)); 447923c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_SUPER_PRIMARY, c.getLong(COLUMN_IS_SUPER_PRIMARY)); 44807a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 44819261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 44829261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana dataValues.put(GroupMembership.GROUP_SOURCE_ID, 44839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.getString(COLUMN_GROUP_SOURCE_ID)); 44849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 44857a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 44867a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana for (int i = 0; i < DATA_KEYS.length; i++) { 44877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 44887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 44897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 44907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 44917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 44927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 44937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 44947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 44957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 44967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 44977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 44987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 44997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 45027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 45037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 45057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4508226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana /** 4509226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 4510226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 4511226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana */ 4512226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static class GroupsEntityIterator implements EntityIterator { 4513226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private final Cursor mEntityCursor; 4514226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private volatile boolean mIsClosed; 4515226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4516226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final String[] PROJECTION = new String[]{ 4517226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups._ID, 4518226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_NAME, 4519226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_TYPE, 4520226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.SOURCE_ID, 4521226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.DIRTY, 4522226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.VERSION, 4523226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.RES_PACKAGE, 4524226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE, 4525226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE_RES, 45267a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.GROUP_VISIBLE, 45277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC1, 45287a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC2, 45297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC3, 45307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC4, 45317a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYSTEM_ID, 453294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.NOTES, 45331a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey Groups.DELETED, 45341a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey Groups.SHOULD_SYNC}; 4535226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4536226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ID = 0; 4537226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_NAME = 1; 4538226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_TYPE = 2; 4539226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_SOURCE_ID = 3; 4540226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_DIRTY = 4; 4541226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_VERSION = 5; 4542226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_RES_PACKAGE = 6; 4543226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE = 7; 4544226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE_RES = 8; 4545226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_GROUP_VISIBLE = 9; 45467a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 10; 45477a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 11; 45487a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 12; 45497a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 13; 45507a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYSTEM_ID = 14; 45517a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_NOTES = 15; 455294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana private static final int COLUMN_DELETED = 16; 45531a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private static final int COLUMN_SHOULD_SYNC = 17; 4554226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4555226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 4556226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 4557226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = false; 4558226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4559226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String updatedSortOrder = (sortOrder == null) 4560226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ? Groups._ID 4561226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana : (Groups._ID + "," + sortOrder); 4562226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4563b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = provider.mDbHelper.getReadableDatabase(); 4564226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 4565b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(provider.mDbHelper.getGroupView()); 4566226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setProjectionMap(sGroupsProjectionMap); 4567226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (groupIdString != null) { 4568226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups._ID + "=" + groupIdString); 4569226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4570226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountName = uri.getQueryParameter(Groups.ACCOUNT_NAME); 4571226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountType = uri.getQueryParameter(Groups.ACCOUNT_TYPE); 4572226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!TextUtils.isEmpty(accountName)) { 4573226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups.ACCOUNT_NAME + "=" 4574226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4575226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + Groups.ACCOUNT_TYPE + "=" 4576226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 4577226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4578226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 4579226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana null, null, updatedSortOrder); 4580226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToFirst(); 4581226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4582226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4583226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public void close() { 4584226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4585226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("closing when already closed"); 4586226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4587226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = true; 4588226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.close(); 4589226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4590226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4591226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public boolean hasNext() throws RemoteException { 4592226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4593226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 4594226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4595226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4596226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return !mEntityCursor.isAfterLast(); 4597226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4598226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4599038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4600038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4601038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4602038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4603038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4604038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4605e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4606226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public Entity next() throws RemoteException { 4607226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4608226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 4609226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4610226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!hasNext()) { 4611226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 4612226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4613226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4614226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 4615226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4616226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final long groupId = c.getLong(COLUMN_ID); 4617226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4618226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana // we expect the cursor is already at the row we need to read from 4619226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ContentValues groupValues = new ContentValues(); 4620226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 4621226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 4622226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups._ID, groupId); 4623226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 4624226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 4625226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 4626226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 4627226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 4628226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 4629226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 46307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC1, c.getString(COLUMN_SYNC1)); 46317a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC2, c.getString(COLUMN_SYNC2)); 46327a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC3, c.getString(COLUMN_SYNC3)); 46337a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC4, c.getString(COLUMN_SYNC4)); 46347a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYSTEM_ID, c.getString(COLUMN_SYSTEM_ID)); 463594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana groupValues.put(Groups.DELETED, c.getLong(COLUMN_DELETED)); 46367a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.NOTES, c.getString(COLUMN_NOTES)); 46371a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey groupValues.put(Groups.SHOULD_SYNC, c.getString(COLUMN_SHOULD_SYNC)); 4638226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Entity group = new Entity(groupValues); 4639226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4640226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToNext(); 4641226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4642226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return group; 4643226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4644226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4645226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4646a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 46477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 46487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 4649568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 4650568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 46517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 46527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 46535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: 46545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: 46557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 46565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (match == RAW_CONTACTS_ID) { 46577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 46587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 46597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 466046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana return new RawContactsEntityIterator(this, uri, contactsIdString, 466146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana selection, selectionArgs, sortOrder); 4662226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS: 4663226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS_ID: 4664226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String idString = null; 4665226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (match == GROUPS_ID) { 4666226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana idString = uri.getPathSegments().get(1); 4667226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4668226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4669226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return new GroupsEntityIterator(this, idString, 4670226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana uri, selection, selectionArgs, sortOrder); 46717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 46727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 46737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 46747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 46757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 46764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 46774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4678a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 46794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4680b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4681b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP: 4682be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 4683b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4684b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4685b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4686f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 4687f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 4688b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4689be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4690b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4691b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4692508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4693b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 469448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 469548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 469648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 469748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 469848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 469948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 470048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 470148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 470248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 470348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 470448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 470548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4706b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4707b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4708b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4709b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4710b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4711b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4712b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4713b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4714c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4715c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4716c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4717c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 471861efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 471961efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 47204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 472325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private void setDisplayName(long rawContactId, String displayName, int bestDisplayNameSource) { 47243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 472525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindString(1, displayName); 47263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 472725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindNull(1); 47283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 472925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(2, bestDisplayNameSource); 473025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(3, rawContactId); 473125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 47323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 47333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 473473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 473573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 473673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 473773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 473873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.bindLong(1, rawContactId); 473973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.execute(); 474073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 474173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4742c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4743c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 4744c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 4745c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4746c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4747c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4748653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 4749c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 4750653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 4751653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 4752c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 4753c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4754c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 4755c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4756c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 4757c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 4758c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4759c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4760c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4761653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 4762c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 4763653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 4764653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 4765c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 4766c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4767ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4768f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 4769f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 4770f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4771f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4772f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4773f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); 4774f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (tokens.length == 0) { 4775f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4776f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4777f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4778f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String address = tokens[0].getAddress(); 4779f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int at = address.indexOf('@'); 4780f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (at != -1) { 4781f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov address = address.substring(0, at); 4782f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4783f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4784f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4785f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 4786f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4787f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4788f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4789f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 4790f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4791f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 4792f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 4793f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4794f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4795f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4796f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4797f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 4798f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4799f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4800a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 4801a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 4802a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 4803a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4804a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 4805a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4806a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 4807a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4808a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 4809a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4810a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4811f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4812f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name) { 4813f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name); 4814f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4815f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4816f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4817f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Returns nickname cluster IDs or null. Maintains cache. 4818f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4819f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4820f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SoftReference<String[]> ref; 4821f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4822f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4823f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (mNicknameClusterCache.containsKey(normalizedName)) { 4824f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = mNicknameClusterCache.get(normalizedName); 4825f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (ref == null) { 4826f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return null; 4827f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4828f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = ref.get(); 4829f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4830f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4831f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4832f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (clusters == null) { 4833f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = loadNicknameClusters(normalizedName); 4834f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = clusters == null ? null : new SoftReference<String[]>(clusters); 4835f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4836f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNicknameClusterCache.put(normalizedName, ref); 4837f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4838f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4839f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4840f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4841f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4842f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] loadNicknameClusters(String normalizedName) { 4843b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4844f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4845f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupQuery.TABLE, NicknameLookupQuery.COLUMNS, 4846f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.NAME + "=?", new String[] { normalizedName }, 4847f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov null, null, null); 4848f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov try { 4849f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int count = cursor.getCount(); 4850f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (count > 0) { 4851f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = new String[count]; 4852f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov for (int i = 0; i < count; i++) { 4853f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.moveToNext(); 4854f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters[i] = cursor.getString(NicknameLookupQuery.CLUSTER); 4855f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4856f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4857f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } finally { 4858f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.close(); 4859f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4860f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4861f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4862f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4863f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 4864f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4865f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 4866f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 4867f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4868f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4869f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4870f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 4871f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 4872f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 4873f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4874f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4875f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4876f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4877f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return ContactsProvider2.this.getCommonNicknameClusters(normalizedName); 4878f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4879f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4880f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4881f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4882f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 4883f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4884f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 4885f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 1, rawContactId); 4886f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 2, dataId); 4887f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 3, lookupType); 4888f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 4, name); 4889f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 4890f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4891f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4892f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4893f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 4894f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4895f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 4896f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupDelete, 1, dataId); 4897f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 4898f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4899f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 49002d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 4901d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4902d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 4903d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4904d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 4905d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 4906d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 4907d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 4908e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 4909d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN(" 4910d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 4911d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 4912d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NICKNAME + "," 4913d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.ORGANIZATION + "))"); 4914e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 4915e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 49165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 4917c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4918c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 4919c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 4920c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4921c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4922a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 4923c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit) { 492420938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), limit, 492520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov true); 49265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 49275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 49285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 492920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String limit, boolean allowEmailMatch) { 4930d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4931d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + NameLookupColumns.RAW_CONTACT_ID + 4932d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 4933d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 4934d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 49355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 4936a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 4937a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 4938a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 493920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov + NameLookupType.ORGANIZATION); 494020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 494120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 494220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 494320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(")"); 49443de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 4945c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limit != null) { 4946c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(" LIMIT ").append(limit); 4947c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4948c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(")"); 4949ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4950ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 49514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 49524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 49534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 49544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 4955b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 4956b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 4957b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 4958b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 4959b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 49604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 49614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 4962b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 4963b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4964b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4965caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 49665e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 49675e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 49685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 49695e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 49705e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 49715e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 49725e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 49735e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 49745e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 49755e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 49765e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 4977caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 4978caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 4979caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 4980df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 4981df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 4982caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 4983caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 4984caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 4985caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 49866f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 4987caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 49886f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 4989caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 49904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 4991