ContactsProvider2.java revision f01c876a92b9c950a0450ed8b706ac5eb2c9b660
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.GroupsColumns; 28b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 29b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 30b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 31b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NicknameLookupColumns; 32b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 33b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 34b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 35b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 36b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 37b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 38b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 39a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Lists; 40a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Maps; 41a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Sets; 423de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 43b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 44caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 455b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 46c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 47568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 48568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 496ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 5035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 53627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.IContentService; 54568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 553d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 56627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 5767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 583de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.content.SharedPreferences.Editor; 59b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 601129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikovimport android.database.CharArrayBuffer; 614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 62ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 63a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 64b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 67c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 696ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 70d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 71b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 720e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 73d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 75508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 763de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 773de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.LiveFolders; 783de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.OpenableColumns; 793de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.SyncStateContract; 80b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 813de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 823de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.DisplayNameSources; 845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.FullNameStyle; 853de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 863de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.PhoneticNameStyle; 883de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 893de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 9082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 92ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 93ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 97de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 98b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 994097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 10067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 101a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 102a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 103f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Token; 104f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer; 105c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 107d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 108b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 109d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 110d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 111f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport java.lang.ref.SoftReference; 1127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 113315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikovimport java.util.BitSet; 1145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 115b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1160e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 118622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 119b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1200e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 121ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1275b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 128caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 129bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 130bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 131bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 133619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 134619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 135619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1453d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1463d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1470e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1480e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 149a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1515e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final String TIMES_CONTACED_SORT_COLUMN = "times_contacted_sort"; 1525e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 1545e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar + TIMES_CONTACED_SORT_COLUMN + " DESC, " 1559b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 156d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 157d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 158d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 159d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1606e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 1619b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 1629b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1639b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 1649b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 1656e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 1669b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 1679b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1689b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 1699b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 170d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 171d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 180f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 1814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 18546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 1864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1876bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1886bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 189ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 19048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 19148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 19248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 19348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 19448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 19548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 19648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 19748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 198a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1996bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 2006bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 201b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 202b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 203b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 20482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 20582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 2061f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 20731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 20831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 209eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 210eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 211ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 212ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 213ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 214ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 21535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 216b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 21735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 218c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 219c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 220c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 22646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 22746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 228d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 229f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 230f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 231f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 23267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 23367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2346cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 236f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 237ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 238ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 239d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 24067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 241d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 242ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 24414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 24567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 24788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 252f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 25388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 25488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 25588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 25688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 25788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 25888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 25988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 260f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 2613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 267f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 2683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 27014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 271321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 27220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 27320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 274321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 275321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 27620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 27720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 278f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 27919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 28019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 28119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 28219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 283ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 284ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 285ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 28619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 28719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 28819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 289ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 290ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 29119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 29219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 293c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 294df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 295caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 29671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 29771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 29871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 29971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 30071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 30171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 30271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 30371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 30471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 30571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 30671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 30771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 30871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 30971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 310a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 311a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 312a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 313a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 314a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 315a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 316a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 317a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 318a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 319a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 320a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 321a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 322038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 323038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 324e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 3265e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 3275e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentStarredProjectionMap; 3285e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentFrequentProjectionMap; 329f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 330f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final HashMap<String, String> sContactsVCardProjectionMap; 331ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 332d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 33346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** Contains the columns from the raw contacts entity view*/ 33446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final HashMap<String, String> sRawContactsEntityProjectionMap; 3354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3399261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 340e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 341ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 342ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 343ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 344ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 345373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 346b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 347eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 348eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 34982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 35082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 3511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 3559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 3569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 3579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 3589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 3599705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 360c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 361c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 363c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 3643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 36525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 36682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 367a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 368f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 369f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 370a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 371a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 372a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 3730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 374a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 375f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov private SQLiteStatement mResetNameVerifiedForOtherRawContacts; 376a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 377f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 378f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 3791129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdStructuredName; 3801129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdOrganization; 3811129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdNickname; 3821129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdPhone; 383f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 3841129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 3851129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 3861129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs3 = new String[3]; 387f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 388f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 3904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 391a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 392d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 393d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 394d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 3953653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 3963653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 3972d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 3982d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 3993653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 4005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 4015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 4025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 403f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 4045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 405ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 406ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 4075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 4083653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 41246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 41346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 41446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 415b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 418ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 41948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4205e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 421ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 42348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 427ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 42848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 430ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 431ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 432ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 433ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 43435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 435b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 436b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 43735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 438a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 439b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 440b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 441b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 442b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 444eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 445eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 44682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 44782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 4481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 449c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 450c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 451c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 452c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 4532d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 454c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 455c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4571b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 4601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 4611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 4621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 4631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 46419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 46519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 46619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 467038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 468038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 469e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 4714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 4725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME_PRIMARY); 4735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 4745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 4755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 4765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 4775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 4785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 4795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, Contacts.SORT_KEY_ALTERNATIVE); 4804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 486f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 4874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 489f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 4903296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 4913296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 4923296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 4933296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 4943296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 4953296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 4963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 4973296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 4983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 4993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 5003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 5013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 5023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 5033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 5045e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5055e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5065e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Long.MAX_VALUE + " AS " + TIMES_CONTACED_SORT_COLUMN); 5075e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5085e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5095e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5105e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Contacts.TIMES_CONTACTED + " AS " + TIMES_CONTACED_SORT_COLUMN); 5115e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 512f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap = Maps.newHashMap(); 513f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 514d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 515ba355248c255551bc65d8023b968513cbe9bcdf3Jeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "NULL AS " + OpenableColumns.SIZE); 5164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 5184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 5194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 5254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 5265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_PRIMARY, 5275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY); 5285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, 5295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE); 5305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_SOURCE, 5315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE); 5325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.PHONETIC_NAME, 5335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME); 5345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.PHONETIC_NAME_STYLE, 5355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE); 536f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.NAME_VERIFIED, 537f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov RawContacts.NAME_VERIFIED); 5385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SORT_KEY_PRIMARY, 5395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY); 5405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SORT_KEY_ALTERNATIVE, 5415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE); 5424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 5434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 5444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 5454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 5464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 5474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 5484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 5494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 5504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 5514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 5524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 5532815f58f72f109790585931f601a63ddc02536a5Evan Millar 5544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 5554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 5564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 5574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 5634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 5644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 5654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 5664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 5674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 5684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 5694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 5704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 5714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 5724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 5734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 5744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 5754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 5764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 5774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 58182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 5824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 587f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov sDataProjectionMap.put(RawContacts.NAME_VERIFIED, RawContacts.NAME_VERIFIED); 58856d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 5915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 5925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 5935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 5945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 5955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 5965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, Contacts.SORT_KEY_ALTERNATIVE); 5974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 6004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 6014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 6024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 603a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 6044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 605a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 60646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana HashMap<String, String> columns; 60746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns = new HashMap<String, String>(); 60846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts._ID, RawContacts._ID); 60946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 61046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 61146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 61246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 61346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.VERSION, RawContacts.VERSION); 61446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 61546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DELETED, RawContacts.DELETED); 616bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey columns.put(RawContacts.IS_RESTRICTED, RawContacts.IS_RESTRICTED); 61746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 61846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 61946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 62046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 621f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov columns.put(RawContacts.NAME_VERIFIED, RawContacts.NAME_VERIFIED); 62246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 62346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.MIMETYPE, Data.MIMETYPE); 62446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA1, Data.DATA1); 62546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA2, Data.DATA2); 62646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA3, Data.DATA3); 62746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA4, Data.DATA4); 62846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA5, Data.DATA5); 62946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA6, Data.DATA6); 63046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA7, Data.DATA7); 63146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA8, Data.DATA8); 63246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA9, Data.DATA9); 63346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA10, Data.DATA10); 63446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA11, Data.DATA11); 63546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA12, Data.DATA12); 63646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA13, Data.DATA13); 63746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA14, Data.DATA14); 63846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA15, Data.DATA15); 63946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC1, Data.SYNC1); 64046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC2, Data.SYNC2); 64146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC3, Data.SYNC3); 64246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC4, Data.SYNC4); 64346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 64446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.STARRED, Data.STARRED); 64546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 64646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 64746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 64846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 64946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana sRawContactsEntityProjectionMap = columns; 65046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 6513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 6523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 6533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 6543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 6553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 6563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 6573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 6613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 6633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 6643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 6663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.PRESENCE, 6673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 6683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS, 6693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 6703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 6713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 6733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_LABEL, 6753296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6763296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_ICON, 6773296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 6783296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 6805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 6815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 6825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 6835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 6845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 6855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 6865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 6875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 6885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 6895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 6905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 6915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 6925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 6935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 6945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 6955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 6965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 6975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 6985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 6995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 7005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 7015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 7025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 7035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 7045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 7055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 7065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 7075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 7088f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 7095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 7105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 7115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 7125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 7135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 7145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 7155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 7165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, 7175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.SORT_KEY_ALTERNATIVE); 7185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 7195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 7205e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 7215e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 7225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 7235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 724a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 7255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 7265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 7275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 7283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 7293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 7303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 7313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 7323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 7333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 7343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 7363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 7383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 7403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 7413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 7433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 7443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 7453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS, 7463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 7473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 7483296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7493296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 7503296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 7523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 7543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 7553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 756e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 757e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 758fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts._ID 759fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup._ID); 76056d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 761fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LOOKUP_KEY 762fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.LOOKUP_KEY); 763e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 764fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.DISPLAY_NAME 765fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.DISPLAY_NAME); 766e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 767fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LAST_TIME_CONTACTED 768e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 769e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 770fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.TIMES_CONTACTED 771fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.TIMES_CONTACTED); 772e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 773fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.STARRED 774fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.STARRED); 775e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 776fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.IN_VISIBLE_GROUP 777fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 778e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 779fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.PHOTO_ID 780fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.PHOTO_ID); 781e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 782fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.CUSTOM_RINGTONE 783fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.CUSTOM_RINGTONE); 784e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 785fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.HAS_PHONE_NUMBER 786fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 787e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 788fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.SEND_TO_VOICEMAIL 789e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 790e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 791e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 792e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 793e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 794e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 795e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 7969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 797ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 798ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 79989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 800035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 801035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 8029261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 8039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 8049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 80589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 806ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 80767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 808ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 8093cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 81094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 8113cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 81238446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 81389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 81489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 81589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 81689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 817ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 818ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 8196cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 820ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 821ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 822d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 823d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 824ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 825ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 826ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 827d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 828d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 829ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 830f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 831ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 832ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 833b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 834b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 835b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 836b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 8370c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 8380c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 839b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 840b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 841eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 842eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 843eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 844eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 845eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 846eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 847341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 848341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 849341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 850fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 851341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 852341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 853341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 85468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 85568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 85668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 85768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 85868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 859e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 86068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 86168936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 86268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 863eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 864eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 865373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 8664dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 8670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 8680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 86982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 87082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 87182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 87270c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 87370c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 87482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 87582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 87682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 87782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 8780a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 8790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 8800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 8810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 8820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 88382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 88419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 8851b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 8861b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 8871b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 8881b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 8891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 8901b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 8911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 8921b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 8931b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 8941b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 8951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 8964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 8974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 8983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 8993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey map.put(toField, fromField + " AS " + toField); 9003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 9013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 9023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 9043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 9063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 908653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 9093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9101129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov @SuppressWarnings("all") 9113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 9123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 913a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 914a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 915a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 916a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 917a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 918a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 919a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 920a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 9213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 923653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 924653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 925b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 926653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 927653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 928653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 929653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 9303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 9323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 934e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 935e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 936e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 937e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 938653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 939e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 940e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 941e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 9423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 9463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 9473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 948653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 949f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 95014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 95114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 952653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 953653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 954653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 955653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 956653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 957653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 958653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 959653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 960653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 961653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 962653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 963653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 964653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 965653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 966653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 967653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 968653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 9694da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 9704da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " =?", mSelectionArgs1); 971653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 972653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 973f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 974653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 975653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 9763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 97914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 98014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 98114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 9824da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 9834da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=?", mSelectionArgs1); 9844da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 9854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=?", mSelectionArgs1); 9863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 9875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 9883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 9903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 9934da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov long mimeTypeId = getMimeTypeId(); 994e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 995e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 9964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 9974da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = db.query(DataDeleteQuery.TABLE, 9984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov DataDeleteQuery.CONCRETE_COLUMNS, 9994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Data.RAW_CONTACT_ID + "=?" + 10004da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov " AND " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId, 10014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 10023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 1003e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 100414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 1005f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 1006e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 1007e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 1008e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 1009e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 10103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 10123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 10133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10144da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (primaryId != -1) { 10154da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov setIsPrimary(rawContactId, primaryId, mimeTypeId); 10164da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 1017e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1018e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1019e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 1020e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 1021e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 1022e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 1023e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1024e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 10253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 102725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 1028285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1029d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(db, rawContactId); 1030fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(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(); 10454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10464da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=?", 10474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 1048622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 1049622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 1050622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 1051622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 1052622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.put(key, cursor.getString(i)); 1053622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1054622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1055622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 1056622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 1057622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1058622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 1059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 1060622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 10643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 10663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1071622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 10723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1073622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 10743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1075622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 10763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 10795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1080622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 108114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 108214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 108314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1084f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1085f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 108625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 108714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 108814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 108914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 109014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 109114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1092f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1093622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1094622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1095cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1096622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1097622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 109814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1099f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 110014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1101f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 1102f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1103f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1104f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 110514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 110625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 110714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 110814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 110914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 111014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 111114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 111214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 111314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 111414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 111514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1116f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 111725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 111814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 11193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1122622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 11233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1124622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1125622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1126622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1127622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 11283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1129622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1130622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1131622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1132622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1133622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1134622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1135622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 113667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1137622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 113867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 113967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1140622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1141622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 11428c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1143622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1144622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 114567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 114667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 114767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 114867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 114967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 115067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 11518c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1152622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 11535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (name.fullNameStyle == FullNameStyle.UNDEFINED) { 11545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mSplitter.guessNameStyle(name); 11555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 11565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 11575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov final String joined = mSplitter.join(name, true); 1158622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 11595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 11605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov update.put(StructuredName.FULL_NAME_STYLE, name.fullNameStyle); 11615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, name.phoneticNameStyle); 1162622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1163622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1164622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1165622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1166622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1167622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1168622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1169622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1170622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1171622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1172622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1173622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1174622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1175622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1176622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1177622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1178622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1179622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1180622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1181622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1182f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1183622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1184622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1185622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1186f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1187622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1188622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1189622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1190622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1191622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1192622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1193622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1194622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1195622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1196622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1197622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1198622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1199622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1200622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1201622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1202622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1203622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1204622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 120567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 120667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 120767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 120867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1209622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1210622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1211622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1212622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1213622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1214622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 121567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 121667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 121767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1218622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1219622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1220622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 12213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 12263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 12283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 12293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 12313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 12323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 12333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 12343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1238622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1239622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1240622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1242622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1243622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1244f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1245622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1246622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1247622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1248f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1249622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1251622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1252622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1253622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1254622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1255622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1256622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1257622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1258622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 12593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1260622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1261622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1262622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1263622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1264622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 12693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 12713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 12723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1276a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1277a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1278a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1279a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1280a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 128125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1282a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1283a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 12843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 128714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1288f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1289a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1290a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1291a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 129214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 129314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1294f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 129514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1297a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 1298a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 129914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 130014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 130114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 130214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1303a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 130414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 130514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 130614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 130725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1308a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 130914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 131014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 131114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 131214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 13133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 13143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 13153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 13163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 13173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 13183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 13193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1321a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1322a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1323a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1324a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1325a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 13263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1328e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1329e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1330e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1331e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1332e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1333e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1334e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 13355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 133614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 133714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 133814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 133914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 134025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1341f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 134214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 134314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 134414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 134514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 134614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1347f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 134814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 134914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 135014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 135114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1352f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 135314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1354f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1355f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 135625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 135714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 135814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 135914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 136014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 136114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 136214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 136314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 136414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 136514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1366f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 136725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 136814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1369e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1370e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1371e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1372e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1373e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1374e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1375e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1376e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1377e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1378e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1379e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1380e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1381e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1382e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 138314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 138414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 138514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 138614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 138714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 138814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 138914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 139014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 139114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 139214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 139314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 139414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 139525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1396f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 139714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 139814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 139914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 140014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 140114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1402f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 140314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 140414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 140514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 140614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1407f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 140814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1409f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1410f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 141125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 141214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 141314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 141414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 141514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 141614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 141714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 141814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 141914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 142014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1421f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 142225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 142314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 142414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 142514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 142614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 14273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 14283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 14303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 14313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 14345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 14350b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 14360b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 14370b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 14380b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1439653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14400b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1441653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14420b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1443285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 144425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 14450b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 14460b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 14470b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1448653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1449653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1450653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1451653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1452653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1453f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 145414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 145514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 14560b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 14570b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 14580b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1459653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1460f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1461653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14620b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1463285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 146425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 14650b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 1466f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 14670b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 146814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 146914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 147014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 147114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 147214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 147314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 147414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 147514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 147614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 147714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1478285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 147925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 148014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1481653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1482653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1483653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1484e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1485e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1486e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1487e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1488653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1489653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1490653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1491e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1492653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1493653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1494e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1495653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 14965ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1497653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1498e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 149936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.MIN_MATCH, 150036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov PhoneNumberUtils.toCallerIDMinMatch(number)); 150136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov 1502653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1503653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 15044da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 15054da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=?", mSelectionArgs1); 1506e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 15073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 15103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 15113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 15123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 15133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 15143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 15153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 15163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 15173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 15183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 15193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 15203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 15213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1525653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1526653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1527653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1528653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1529653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1530653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1531653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1532653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1533653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 15340be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 15350be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15360be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1537653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1538653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1539653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1540653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1541f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 154214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1543653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1544f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 15450be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15460be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 15470be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 15480be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 15490be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 15500be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 15510be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 15520be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15530be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 15540be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 15550be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 15560be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1557b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 15580be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1559b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 15600be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1561653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1562653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1563653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1564653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1565653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1566653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1567653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1568653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1569653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1570653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1571653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1572653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1573653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1574653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1575653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1576653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1577653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1578653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1579653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1580653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1581653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1582653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1583653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1584653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1585ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId, 1586ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.get(rawContactId)); 1587653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1588653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1589653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1590653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1591a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1592a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1593a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1594a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1595a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1596653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1597653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1598a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1599a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1600a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1601a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1602a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1603a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1604a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1605a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1606a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1607285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1608285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1609285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1610a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1611a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1612a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1613a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1614a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1615f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1616a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1617f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1618a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1619a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1620a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1621a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1622a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1623a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1624a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1625a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1626a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1627a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1628a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1629a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1630a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1631a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1632a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1633a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1634a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1635ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov /** 1636ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 1637ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1638ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1639ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov public class GroupIdCacheEntry { 1640ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1641ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 1642ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1643ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1644ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1645a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 16463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 1647b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 164831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 16494097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1650f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1651315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1652315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov // We will use this much memory (in bits) to optimize the nickname cluster lookup 1653315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private static final int NICKNAME_BLOOM_FILTER_SIZE = 0x1FFF; // =long[128] 1654315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private BitSet mNicknameBloomFilter; 1655315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1656ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, SoftReference<String[]>> mNicknameClusterCache = Maps.newHashMap(); 1657ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 1658622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1659622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1660ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1661ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1662ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // is a list of groups with this group id. 1663ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1664ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 1665622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1666f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1667a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1668a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 166920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 16701129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private CharArrayBuffer mCharArrayBuffer = new CharArrayBuffer(128); 16715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private NameSplitter.Name mName = new NameSplitter.Name(); 167220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1673ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 167473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1675ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<Long, Account> mInsertedRawContacts = Maps.newHashMap(); 1676b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1677a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private HashSet<Long> mDirtyRawContacts = Sets.newHashSet(); 1678b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1679de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 16801a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 16811a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 168281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 168381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 16844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 16854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1686de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1687ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1688ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1689ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1690ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1691ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1692ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1693ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 169435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1695ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 1696de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1697b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1698a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1699b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1700d076a108d58b30591f197e1b90fa8de60999c499Dmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper); 17010e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1702a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1703b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 1704653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1705c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1706653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1707653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1708653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1709653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1710653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1711c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1712653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1713653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1714653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1715653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1716653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1717653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1718653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1719653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1720653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1721653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1722653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 172325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate = db.compileStatement( 172425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 17255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov " SET " + 17265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE + "=?," + 17275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY + "=?," + 17285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," + 17295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME + "=?," + 17305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE + "=?," + 17315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY + "=?," + 17325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE + "=?" + 173325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 17343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1735a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate = db.compileStatement( 1736a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.CONTACTS + 1737a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1738a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1739a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1740a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1741a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1742a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1743a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1744a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1745a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1746a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 17470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 17480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1749a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " LIMIT 1)" + 1750a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1751e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 17525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov final Locale locale = getLocale(); 175328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 175428f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 175528f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 175628f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 1757622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey context.getString(com.android.internal.R.string.common_name_conjunctions), 1758622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey locale); 1759f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 1760622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mPostalSplitter = new PostalSplitter(locale); 17614097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1762f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1763f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1764f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1765f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1766f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1767f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1768f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1769a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert = db.compileStatement( 1770a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1771a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 1777a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1778a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace = db.compileStatement( 1779a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1780a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 17820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17840a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17850a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1787a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1788a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp = db.compileStatement( 1789a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 17910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 1792a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 17930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 17940a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 17950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate = db.compileStatement( 17960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 17980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 17990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 18000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1801a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1802a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete = db.compileStatement( 1803a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1804a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1805a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1806f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // When setting NAME_VERIFIED to 1 on a raw contact, reset it to 0 1807f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // on all other raw contacts in the same aggregate 1808f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts = db.compileStatement( 1809f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 1810f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " SET " + RawContacts.NAME_VERIFIED + "=0" + 1811f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=(" + 1812f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1813f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1814f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?)" + 1815f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " AND " + RawContacts._ID + "!=?"); 1816f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 18173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 18183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1819e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 18203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 18213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 182267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 182367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 18243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 18253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 182614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 18273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 18283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1829622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1830622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1831a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1832a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 18333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 18343d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1835568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 18363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1837568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1838c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov verifyAccounts(); 183970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 1840f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1841f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 18421129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdStructuredName = mDbHelper.getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE); 18431129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdOrganization = mDbHelper.getMimeTypeId(Organization.CONTENT_ITEM_TYPE); 18441129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdNickname = mDbHelper.getMimeTypeId(Nickname.CONTENT_ITEM_TYPE); 18451129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdPhone = mDbHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 1846315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov preloadNicknameBloomFilter(); 18471f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 18484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 18494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1850c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 1851c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1852c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1853c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 1854c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 185531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1856de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1857b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1858b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 185931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 186031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1861013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1862013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1863013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1864013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 18655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 18665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 18675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 18685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 18695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 18703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 18713d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18723d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 18733d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1875568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1876568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1877568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1878568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1879568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1880568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1881568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1882568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1883568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1884ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1885568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1886568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1887568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1888568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1889568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1890d076a108d58b30591f197e1b90fa8de60999c499Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1891568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1892568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1893568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1894568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1895568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1896ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1897ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1898568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1899568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1900568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1901568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1902568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1903568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1904568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1906568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1907568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 19083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 19093d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 19103d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 19113d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 19123d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 19133d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 19143d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 19153d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19163d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19173d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 19183d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1919568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 19200e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 19213d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 19223d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 19233d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 19240e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(aggregatorEnabled); 19253d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 19263d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 19273d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 19283d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 19293d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19303d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19313d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1932a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1933a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1934a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1935a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1936b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 1937a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1938a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1939568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1940568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 1941568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1942568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1943568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1944568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1945568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1946568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 1947ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 1948ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 1949ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 1950ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 1951ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 1952ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1953ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 1954ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 195581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 1956ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1957ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1958568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1959568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1960568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1961568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1962568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1963568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1964568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1965568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1966568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1967568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1968568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1969568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1970568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1971568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1972568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1973568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1974568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 1975568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1976568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1977568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1978568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1979568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1980568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1981568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 1982568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1983568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1984568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1985568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1987285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1988bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1989b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1990b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1991285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 19921ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1993b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1994b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1995b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1996b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 1997285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 1998b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 1999df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 2000a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.clear(); 2001285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2002285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2003285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2004285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 20051129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 2006bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2007b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2008b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2009285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 2010b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 20111ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 20121a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 20131a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 2014b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 20151a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 2016b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2017b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2018b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2019bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2020b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2021b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 20221129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 202308e42c9c153a60bf2e7c71dd40bf84bb5fc93555Dmitri Plotnikov for (long rawContactId : mInsertedRawContacts.keySet()) { 2024d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(mDb, rawContactId); 2025d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mContactAggregator.onRawContactInsert(mDb, rawContactId); 2026285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2027b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2028a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov if (!mDirtyRawContacts.isEmpty()) { 2029a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2030a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2031a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mDirtyRawContacts); 2032a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2033a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2034a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2035a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2036b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 2037a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2038a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2039a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mUpdatedRawContacts); 2040a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2041a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2042b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2043b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2044b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 2045b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 2046b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().update(mDb, id, entry.getValue()); 2047b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2048b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2049b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2050b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2051b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2052a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2053a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2054a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2055a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2056a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private void appendIds(StringBuilder sb, HashSet<Long> ids) { 2057b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2058a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2059b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2060a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2061a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2062285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2063285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2064285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2065cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 206681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 206781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 206881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 206981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 207081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 207181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 207281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2073cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2074568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2075285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 2076ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return mInsertedRawContacts.containsKey(rawContactId); 2077285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2078285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 20793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 20803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 20813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 20823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 20833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 20843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 20863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 20884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2089de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2090bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 20911129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2092b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2093f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2094f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2095f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2096f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2097a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2098a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 209935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2100a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 210135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2102b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 210335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 210435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2105d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2106d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 21076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 21086bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 21096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 21105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2111f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertRawContact(uri, values); 2112f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2113a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2114a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2115a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 21165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 21175ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2118f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2119f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2120a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2121a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2122a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2123a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2124f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2125f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2126a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2127a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2128a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2129ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2130f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2131f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2132ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2133ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2134ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2135eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 21365aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 213743880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2138eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2139eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2140eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 214182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 214282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 21431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 21441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 21451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2146a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 214781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2148f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2149a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2150a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 21517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 21527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 21537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2155de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2156a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2157a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2158a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2159e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2160e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2161e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2162e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2163e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2164e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2165e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2166e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2167e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2168e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2169e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2170e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2171e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 21727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2173e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2174f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2175f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2176e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2177f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2178f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2179f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2180e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2181e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2182e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2183e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2184e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 2185e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey throw new IllegalArgumentException("Must specify both or neither of" 2186e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + " ACCOUNT_NAME and ACCOUNT_TYPE"); 2187e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2188e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2189e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2190e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2191e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2192e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2193e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2194e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2195e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2196e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2197e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2198e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 2199e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey throw new IllegalArgumentException("When both specified, " 2200e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + " ACCOUNT_NAME and ACCOUNT_TYPE must match"); 2201e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2202e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2203e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2204f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2205f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2206e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2207f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2208f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2209e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2210e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2211f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2212f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2213e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2214f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2215f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2216f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2217f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2218035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2219f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2220e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 22217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 22227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 22237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2224d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 22256bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 22266bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 22276bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 22286bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2229d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2230de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 22316bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 22326bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 22336bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2234a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2235a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2236f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2237f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2238a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2239a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2240f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertRawContact(Uri uri, ContentValues values) { 2241f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2242f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2243f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2244f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2245e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 22467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 22473d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 22483d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2249f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 22503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 22513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2252f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 2253023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 2254285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2255285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2256e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mInsertedRawContacts.put(rawContactId, account); 2257f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2258023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2259a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2260a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2261a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2262a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2263a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2264a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2265a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2266a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2267f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2268a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2269de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2270de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 227167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2272de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 227320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2274de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2275de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2276de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2277b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2278de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2279de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2280508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2281de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2282de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2283de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2284de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2285de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 22864097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2287b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2288de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2289a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2290a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2291a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2292f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2293de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2294a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2295b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2296a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2297a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2298a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2299a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2300a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 23014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 23024f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 23038e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 23048e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 23058e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 23068e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 23078e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2308b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2309f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 23108e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 23118e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 23128e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 23138e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2314421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 2315f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 23168e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 23178e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 23188e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2319b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2320f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 23218e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 23228e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 23238e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2324f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 23258e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2326f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2327c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 2328b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 23298e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2330f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 23318e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2332f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2333f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2334f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2335a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 23365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 23379261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 23389261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 23395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 23409261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 23419261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 23429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 23439261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 23449261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 2345ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId, 2346ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Account account) { 2347ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2348ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (account == null) { 23494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 2350ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 23514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov RawContacts._ID + "=?", mSelectionArgs1, null, null, null); 2352ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov try { 2353ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2354ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = c.getString(RawContactsQuery.ACCOUNT_NAME); 2355ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = c.getString(RawContactsQuery.ACCOUNT_TYPE); 2356ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 2357ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov account = new Account(accountName, accountType); 2358ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 23599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2360ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } finally { 2361ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov c.close(); 23629261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23639261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2364ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 23659261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 23669261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 2367ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov + "has a sourceid the the contact must be associated with " 23689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 23699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23709261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2371ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ArrayList<GroupIdCacheEntry> entries = mGroupIdCache.get(sourceId); 2372ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entries == null) { 2373ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries = new ArrayList<GroupIdCacheEntry>(1); 2374ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.put(sourceId, entries); 2375ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2376ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2377ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int count = entries.size(); 2378ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov for (int i = 0; i < count; i++) { 2379ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = entries.get(i); 2380ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entry.accountName.equals(account.name) && entry.accountType.equals(account.type)) { 2381ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 2382ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2383ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2384ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2385ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = new GroupIdCacheEntry(); 2386ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountName = account.name; 2387ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountType = account.type; 2388ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.sourceId = sourceId; 2389ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries.add(0, entry); 2390ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 23919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 23925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 2393ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 23949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2395df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 23969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 2397ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2398ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = c.getLong(0); 23999261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 24009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2401df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2402df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 24039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 24049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 24059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 24069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 24079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 24089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2409ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = groupId; 24109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 24119261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 24129261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 24139261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2414ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2415ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 24169261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 24179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2418d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private interface DisplayNameQuery { 24191129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov public static final String RAW_SQL = 24201129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov "SELECT " 24211129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + DataColumns.MIMETYPE_ID + "," 24221129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.IS_PRIMARY + "," 24231129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.DATA1 + "," 24245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA2 + "," 24255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA3 + "," 24265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA4 + "," 24275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA5 + "," 24285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA6 + "," 24295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA7 + "," 24305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA8 + "," 24315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA9 + "," 24325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA10 + "," 24335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA11 + 24341129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " FROM " + Tables.DATA + 24351129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " WHERE " + Data.RAW_CONTACT_ID + "=?" + 24361129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " AND (" + Data.DATA1 + " NOT NULL OR " + 24371129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Organization.TITLE + " NOT NULL)"; 2438d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2439d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int MIMETYPE = 0; 2440d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int IS_PRIMARY = 1; 24415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int DATA1 = 2; 24425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int GIVEN_NAME = 3; // data2 24435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FAMILY_NAME = 4; // data3 24445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PREFIX = 5; // data4 24455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int TITLE = 5; // data4 24465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int MIDDLE_NAME = 6; // data5 24475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int SUFFIX = 7; // data6 24485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_GIVEN_NAME = 8; // data7 24495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_MIDDLE_NAME = 9; // data8 24505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME = 9; // data8 24515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_FAMILY_NAME = 10; // data9 24525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FULL_NAME_STYLE = 11; // data10 24535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME_STYLE = 11; // data10 24545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_NAME_STYLE = 12; // data11 2455d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2456d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2457d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov /** 2458d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * Updates a raw contact display name based on data rows, e.g. structured name, 2459d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * organization, email etc. 2460d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov */ 2461d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 2462bca1c8b44f99528fc123d5547723e44771e8e934Mike Lockwood int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 24635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name bestName = null; 24645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestDisplayName = null; 24655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestPhoneticName = null; 24665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 2467d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 24681129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 24691129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Cursor c = db.rawQuery(DisplayNameQuery.RAW_SQL, mSelectionArgs1); 2470d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov try { 2471d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov while (c.moveToNext()) { 24721129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov int mimeType = c.getInt(DisplayNameQuery.MIMETYPE); 24735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int source = getDisplayNameSource(mimeType); 24745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source < bestDisplayNameSource || source == DisplayNameSources.UNDEFINED) { 24755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 24765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 24771129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 24785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source == bestDisplayNameSource && c.getInt(DisplayNameQuery.IS_PRIMARY) == 0) { 24795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 2480d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 24811129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 24825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mimeType == mMimeTypeIdStructuredName) { 24835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name name; 24845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestName != null) { 24855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = new NameSplitter.Name(); 24865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 24875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = mName; 24885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.clear(); 24895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 24905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.prefix = c.getString(DisplayNameQuery.PREFIX); 24915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.givenNames = c.getString(DisplayNameQuery.GIVEN_NAME); 24925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.middleName = c.getString(DisplayNameQuery.MIDDLE_NAME); 24935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.familyName = c.getString(DisplayNameQuery.FAMILY_NAME); 24945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.suffix = c.getString(DisplayNameQuery.SUFFIX); 24955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.fullNameStyle = c.isNull(DisplayNameQuery.FULL_NAME_STYLE) 24965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? FullNameStyle.UNDEFINED 24975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.FULL_NAME_STYLE); 24985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticFamilyName = c.getString(DisplayNameQuery.PHONETIC_FAMILY_NAME); 24995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticMiddleName = c.getString(DisplayNameQuery.PHONETIC_MIDDLE_NAME); 25005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticGivenName = c.getString(DisplayNameQuery.PHONETIC_GIVEN_NAME); 25015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticNameStyle = c.isNull(DisplayNameQuery.PHONETIC_NAME_STYLE) 25025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 25035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.PHONETIC_NAME_STYLE); 25045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (!name.isEmpty()) { 25055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 25065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName = name; 25075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else if (mimeType == mMimeTypeIdOrganization) { 25095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 25105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 25115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 2512d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov bestDisplayNameSource = source; 25131129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 25141129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 25155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = c.getString(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME); 25165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = 25175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.isNull(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE) 25185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 25195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE); 25205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 25215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.TITLE, mCharArrayBuffer); 25225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 25231129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayNameSource = source; 25241129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 25251129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 25265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 25275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 25281129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 2529d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 25305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 25315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Display name is at DATA1 in all other types. 25325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // This is ensured in the constructor. 25335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 25345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 25355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 25365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 25375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 25385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 25395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 25405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 25415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 25425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 2543d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2544d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2545d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2546d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } finally { 2547d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov c.close(); 2548d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2549d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 25505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary; 25515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNameAlternative; 25525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyPrimary = null; 25535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyAlternative = null; 25545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int displayNameStyle = FullNameStyle.UNDEFINED; 25555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 25565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestDisplayNameSource == DisplayNameSources.STRUCTURED_NAME) { 25575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = bestName.fullNameStyle; 25585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.CJK 25595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.UNDEFINED) { 25605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 25615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName.fullNameStyle = displayNameStyle; 25625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 25645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = mNameSplitter.join(bestName, true); 25655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative = mNameSplitter.join(bestName, false); 25665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 25675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = mNameSplitter.joinPhoneticName(bestName); 25685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = bestName.phoneticNameStyle; 25695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 25705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = displayNameAlternative = bestDisplayName; 25715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 25735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticName != null) { 25745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = bestPhoneticName; 25755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticNameStyle == PhoneticNameStyle.UNDEFINED) { 25765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = mNameSplitter.guessPhoneticNameStyle(bestPhoneticName); 25775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 25795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED) { 25805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.guessFullNameStyle(bestDisplayName); 25815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED 25825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.CJK) { 25835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedNameStyleBasedOnPhoneticNameStyle( 25845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle, bestPhoneticNameStyle); 25855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 25875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.CHINESE) { 25895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = 25905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameSplitter.convertHanziToPinyin(displayNamePrimary); 25915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 25945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (sortKeyPrimary == null) { 25955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = displayNamePrimary; 25965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyAlternative = displayNameAlternative; 25975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 25995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov setDisplayName(rawContactId, bestDisplayNameSource, displayNamePrimary, 26005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative, bestPhoneticName, bestPhoneticNameStyle, 26015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary, sortKeyAlternative); 2602d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2603d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 26041129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private int getDisplayNameSource(int mimeTypeId) { 26051129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (mimeTypeId == mMimeTypeIdStructuredName) { 26061129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.STRUCTURED_NAME; 26071129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdEmail) { 26081129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.EMAIL; 26091129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdPhone) { 26101129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.PHONE; 26111129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdOrganization) { 26121129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.ORGANIZATION; 26131129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdNickname) { 26141129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.NICKNAME; 26151129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else { 26161129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.UNDEFINED; 26171129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 26181129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 26191129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 26209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 262120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 262220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2623f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 262420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 262520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2626de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2627de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 262814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2629de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2630de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 263114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 263214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2633a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2634a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2635f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 263688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 2637a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2638a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2639a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 264088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 264120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 264220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2643de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 264420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 264520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 264620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 264720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 264820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 264988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 265088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 265188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 265220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2653f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 265488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 265588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 26564da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 26574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=?", 26584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 2659f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 266020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 266120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 266220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 266320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 266420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 266514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 266620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 266720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 266820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 266920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 267020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 267120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 267220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 267320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 267420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 26757a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 267620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 267720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 267820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2679a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2680a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 26818e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2682a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2683a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2684a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 26858e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 268620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 268720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 268820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 268920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 269020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 269120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2692ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2693ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2694f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2695f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2696f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2697f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2698e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 2699ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2700ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 2701f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 270267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 2703f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 270467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 2705f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 2706ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2707f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2708f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 270973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 271073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2711f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 2712ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2713f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 27141a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2715ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2716ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2717ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2718ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2719ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 27205aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2721e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 27225aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 27231a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 27241a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2725e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 27261a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 2727e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2728e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2729e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2730ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 273182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 27321f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 273382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 273482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 27350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 27364dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 27374dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 27380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 273982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 27404dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 27414dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 27424dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 27434dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 27441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 27451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2746dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 2747dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 274882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 2749f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 2750dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 2751dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 2752dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2753f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "="); 2754f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(dataId); 27551f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 2756dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 2757dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 27580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 27590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 27600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 27610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2762dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 2763dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 2764dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2765dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 2766f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2767f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 2768f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 2769f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 2770f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2771f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 2772f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 2773f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (") 2774f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2775f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(",") 2776f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2777f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(")" + " AND " + Data.DATA1 + "="); 2778f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2779f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ((" + DataColumns.MIMETYPE_ID + "=") 2780f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2781f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2782f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol); 2783dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2784f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2785f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2786dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2787f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=") 2788f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2789f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append("))"); 2790dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 2791f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=") 2792f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2793f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2794f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol) 2795f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.DATA + "="); 2796f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2797dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2798f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2799f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2800dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2801dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 28021f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 280382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 2804f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=") 280582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .append(values.getAsLong(StatusUpdates.DATA_ID)); 2806dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 280770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 2808f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 280970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 28101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 28111f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2812de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 2813c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov mSb.toString(), null, null, null, 2814c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 28151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 281667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 28175ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2818e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 28191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 28201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 28211f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 28221f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 28231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 282431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 282531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 282631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 28271f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 28281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 282982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2830a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2831a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2832a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2833a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2834a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2835a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2836a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 283782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2838a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2839a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 284082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 284182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 284282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 284382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 284482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2845a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 284682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 284782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 28481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2849a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2850a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2851a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2852e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 28530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 285482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 285582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 28560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 28570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 28580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 28590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 28600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 28610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 28620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 28630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 28640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 28650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 28660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 28670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2868a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 2869a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 2870a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 287182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 287282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 2873a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 2874a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 28755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 3, status); 28765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 4, resPackage); 28775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 5, iconResource); 28785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 6, labelResource); 2879a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 2880a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 2881a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2882a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 2883a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 28845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 2, status); 28855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 3, resPackage); 28865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 4, iconResource); 28875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 5, labelResource); 2888a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 2889a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 2890a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 28910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 2892a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 28935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 2, status); 2894a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 28955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 4, status); 2896a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 28970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 28985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusAttributionUpdate, 1, resPackage); 28995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 2, iconResource); 29005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 3, labelResource); 29010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 29020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 2903a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2904e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2905e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2906bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2907a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2908a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 2909a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 2910a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 2911a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2912a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2913a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 29141f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 29151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 29164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2917de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2918bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2919b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2920b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2921b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2922f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2923f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2924508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2925508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 292635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2927b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 292835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2929b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2930b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2931b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2932b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2933b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2934b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2935cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2936cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2937cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2938cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2939cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2940d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2941d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2942cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 29436bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 29446bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 29452e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 29462e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 29472e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 29482e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 29492e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 29502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 29512e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 29522e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 29532e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 29542e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 29552e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 29562e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 29572971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 29582971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 2959fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, 2960fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 2961e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 29622971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 29632971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 29642971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2965fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 2966fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 2967fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 29682971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 29692971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 29702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 29712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 29722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 29732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 29742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 29755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 29762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2977fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return deleteRawContact(rawContactId, mDbHelper.getContactId(rawContactId), 2978fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 2979508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2980508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 298120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2982f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2983944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2984f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 298520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 298620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 298748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 298848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 298948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 299048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2991508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2992f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 29934da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 29944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 2995ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2996ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2997ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2998f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 29995aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 30002971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 30012971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 30022971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 30032971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 30042971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 3005e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 30062971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 30072971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 30085aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 30092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 30102971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 30112971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 30122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 301381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3014f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 301581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 30162971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3017508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3018508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3019eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 302043880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3021e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3022eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3023eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 302482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 30250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 30261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 30271f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 302881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 302981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 30303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 303181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3032508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 30334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 30344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 30351c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3036ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3037b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 303894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 3039de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 304094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 304194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 304294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 304394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3044f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 3045de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 304694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 304794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 304894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3049f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 3050de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 305194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 305294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 30531a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 305494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 305594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 305694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 30575aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 3058e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 30591a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3060e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3061e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3062e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3063cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 3064cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 3065cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null); 3066cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3067cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3068cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3069cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 3070cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3071cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3072cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3073cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3074cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3075cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3076cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3077cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3078fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 30793389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3080f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 308114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 3082fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov int count = mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 3083fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForContact(mDb, contactId); 3084fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 308533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 3086b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 3087cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 308833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 308933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 309033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 30910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 30929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 30939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 30949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 30959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 30969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 30989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 30999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 31000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 31010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3102cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 310381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 310481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3105cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3106cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3107cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3108cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3109cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3110cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3111cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 3112cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3113cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 31144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3115de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3116de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3117bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3118b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3119b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3120b5a4add17815167d20a90645779df34cdf45280dFred Quintana 312135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 312200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 312300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3124b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3125b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 31261129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 3127b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 3128b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3129b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3130b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3131f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3132f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 313300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 313435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3135b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3136b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3137b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3138b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3139b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3140b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3141b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3142b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3143b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3144b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3145b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 314635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3147d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 31488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 314900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 315000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 315100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3152d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 31538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 3154c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3155c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3156c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 31572e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 31582e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 31592e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 31602e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 31612e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 31622e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 31632e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 31642e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 31652e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 31668c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 31672e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 31682e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 31692e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 31707d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 31717d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 31727d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 31737d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 31747d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 31757d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 31767d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 31777d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 31787d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 31797d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 318020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3181944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3182f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 318381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3184f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 318581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 318620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 318720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3188c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 318948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 319048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 319148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 319248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3193f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 319481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3195f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 319681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 319700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 319800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 31997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 32005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 32015ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 32024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 32037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 32047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 32057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 32065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 320733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 32084529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 32094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 32104da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 32114529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 32124529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 32134da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 32144da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1); 32154529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 32167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 32177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 32187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3219ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 32205aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3221f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 322281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3223f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 322481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3225ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3226ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3227ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3228ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3229ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 32304da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 32314da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 323273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 32335aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 32345aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 323581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3236f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 323781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3238ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3239ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3240ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3241127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 3242de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 3243b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3244b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3245b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3246eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3247e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3248e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 324943880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3250eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3251eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3252eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 32539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 32549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 32559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 32569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 32579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 325881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 325981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 3260f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 326181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 326200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 326300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 326400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 32654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 32664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 32679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 32689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 32699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 32709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 32719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 32729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 32739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 32749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 32759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 32769705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 32779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 32789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 32799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 32809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 32819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 32829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 32839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 32849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 32859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 32869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 32879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 32889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 32899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 32909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 32919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 32929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 32939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 32949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 32959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 32969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 32979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 32989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 32999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 33009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 33019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 33029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 33039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 33049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 33059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 33069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 33079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 33089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 33099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 33109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 33119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 33129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 33139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 33149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 33159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 33169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 33179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 33189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 33199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 33209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 33219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 33229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 33239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 33245aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 3325f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 332673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3327ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3328ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 332973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 3330f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 333173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 333273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 333373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 333473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 333573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 333673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 333773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 333873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3339ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 33401a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 33411a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 334294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 33436ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 33441129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 33456ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 3346e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 33476ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 33486ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 33496ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 33506ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 33516ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 33526ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 33536ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 33546ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 33556ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 3356ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 33576ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 33586ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 33596ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 33606ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 33616ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 33626ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 33636ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 33646ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 336594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 336694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 336794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 3368b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 3369b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 3370e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 33711a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 33721a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3373e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3374e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3375e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3376e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 33774529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 33784529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 33794529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 33804529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 33814529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 338273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 33834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3384b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 338551bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 33864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 33874529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 33884529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 33894529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 33904529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 33914529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 33924529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 33934529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 33944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 33954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 33964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 33974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 33984529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 33994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 34004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 340119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final String selection = RawContacts._ID + " = " + rawContactId; 340219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 340319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 340419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 3405ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 3406ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 340719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 340819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 340919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka null, null, null, null); 341019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 341119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 341219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 3413ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 3414ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 341519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 341619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 341719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 341819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 341919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 342019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 342119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 3422f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 342319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int count = mDb.update(Tables.RAW_CONTACTS, values, selection, null); 34245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3425433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 34264529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3427433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3428285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 3429285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateLookupKey(mDb, rawContactId); 3430285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 3431f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 3432f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 3433f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 3434f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 3435f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 3436f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(1, rawContactId); 3437f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(2, rawContactId); 3438f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.execute(); 3439f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 3440f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(mDb, rawContactId); 3441f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 344219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 344319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 3444ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.put(rawContactId, new Account(accountName, accountType)); 344519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 34465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 344833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 344933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3450321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3451f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 345220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 345320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 345420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 34555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 345620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 345720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 345820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 345920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 346020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3461b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 346220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 346320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 346470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 346570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 346620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 346720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 346820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 346970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 347020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 347170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 347220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 347370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 347420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 347570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 347620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 347720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3478653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 347920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3480653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3481653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 348214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 3483653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 3484653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 3485f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 348620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3487653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 3488653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 348920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 349020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3491653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 349220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 349320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3494f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 3495653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 3496653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 3497321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3498653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 349914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 3500a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3501f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana rowHandler.update(mDb, values, c, callerIsSyncAdapter); 35028e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 3503a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 3504a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 3505a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 35068e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 3507653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 3508321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3509321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 35108c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 35118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 35128c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 3513b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 35148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 35158c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 35168c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 35178c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 35188c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 35198c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 35208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 35218c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 35228c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 35238c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 35248c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 35258c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 35268c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 35278c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 35288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 35298c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 3530d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 35318c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3532b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3533d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3534b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 3535d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3536b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 3537d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3538b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3539d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3540b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3541d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 3542d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3543d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 35448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 3545d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 3546d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3547d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 35488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 3549c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 35508c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3551c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 3552c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 35534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 35544da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?", mSelectionArgs1); 35558c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 35568c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 35578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 35588c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3559b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 35608c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3561b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 35628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3563b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 35648c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3565b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 35668c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3567b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 35688c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 35698c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 35709b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori int rslt = mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 35716e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 35729b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 35739b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 35749b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 35759b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 35769b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 35779b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 3578f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3579d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3580127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 3581127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 35820c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 35830c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 358480c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 35850c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 35860c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 35870c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 35880c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 35890c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 35900c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 35910c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 3592b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3593127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 35940c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 35954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 35964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 35970c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 35984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 35994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 36000c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 36016bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 36026bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 36030c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 36040c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 36050c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 36060c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 3607127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 3608127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 36093389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3610dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 3611dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 3612dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 3613b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 36140c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 36150c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 3616b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId2 = mDbHelper.getContactId(rawContactId2); 36170c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 3618127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3619127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 3620127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 3621127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3622b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3623b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 362470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 3625b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 362670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (mDb == null) return; 362770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 3628627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 3629627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov boolean hasUnassignedContacts[] = new boolean[]{false}; 363070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 363170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 3632627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3633627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.RAW_CONTACTS, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE); 3634627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3635627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.GROUPS, Groups.ACCOUNT_NAME, Groups.ACCOUNT_TYPE); 3636627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3637627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.SETTINGS, Settings.ACCOUNT_NAME, Settings.ACCOUNT_TYPE); 363848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3639627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 3640627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // in the existingAccounts set will be extra accounts whose data must be deleted. 3641627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 3642627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 3643627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 364470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 364570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 364670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 36475f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 3648627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 3649627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3650627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 3651627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 3652627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 3653627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3654627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 3655627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 3656627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "SELECT " + RawContacts._ID + 3657627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 3658627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3659627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 3660627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3661627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 3662627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3663627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 3664627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3665627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 3666627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 3667627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 3668627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3669627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3670627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (hasUnassignedContacts[0]) { 3671627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3672627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Account primaryAccount = null; 3673627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 3674627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (isWritableAccount(account)) { 3675627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov primaryAccount = account; 3676627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov break; 3677627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3678627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3679627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3680627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (primaryAccount != null) { 3681627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {primaryAccount.name, primaryAccount.type}; 3682627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3683627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3684627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 3685627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + RawContacts.ACCOUNT_NAME + "=?," 3686627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=?" + 3687627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + 3688627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL", params); 3689627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3690627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // We don't currently support groups for unsynced accounts, so this is for 3691627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // the future 3692627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3693627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.GROUPS + 3694627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + Groups.ACCOUNT_NAME + "=?," 3695627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + Groups.ACCOUNT_TYPE + "=?" + 3696627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " IS NULL" + 3697627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " IS NULL", params); 3698627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 369970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3700627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3701b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 370270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 370370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 370470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 370570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 370670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3707619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3708619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3709627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 3710627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 3711627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov private void findValidAccounts(Set<Account> validAccounts, boolean[] hasUnassignedContacts, 3712627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String table, String accountNameColumn, String accountTypeColumn) { 3713627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Cursor c = mDb.rawQuery("SELECT DISTINCT " + accountNameColumn + "," + accountTypeColumn 3714627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + " FROM " + table, null); 3715627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 3716627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 3717627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (c.isNull(0) && c.isNull(1)) { 3718627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov hasUnassignedContacts[0] = true; 3719627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } else { 3720627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 3721627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3722627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3723627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 3724627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 3725627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3726627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3727627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3728627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov /** 3729622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 3730622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 373167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 373267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 373367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 373467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 373567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 373667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 373767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 373867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 373967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 374067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 374167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 374267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 3743dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 3744622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 3745dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 3746dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 3747622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3748622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3749dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 3750622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3751622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 37524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 37534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 37544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 3755bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3756bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3757bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 37580b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 3759b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 376035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3761d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 37621f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3763c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3764c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3765619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3766619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3767a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 37684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 376935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3770b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 377135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 377235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3773d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3774763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3775619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3776619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3777619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3778d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 37794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3780763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 37814da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 37824da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 37836bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 37846bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 37856bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 37865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 37875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 37885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 37895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 37905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 37915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 37925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 37945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 37952d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill // TODO: pull this out into a method and generalize to not require contactId 37965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 37975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3798763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 37994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String[] args; 38004da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (selectionArgs == null) { 38014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[2]; 38024da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } else { 38034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[selectionArgs.length + 2]; 38044da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 38054da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 38064da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args[0] = String.valueOf(contactId); 38074da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args[1] = lookupKey; 38084da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 38094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 38105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 38115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 38125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 38135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 38165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3818763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 38194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 38204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 38214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 38225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 38235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3825f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 3826f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 3827f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 3828763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 3829f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 38304da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 38314da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 38324da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 3833f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 3834f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 3835f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 3836ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3837763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3838ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 38394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 38404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3841e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 38425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 38434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sb.toString()); 3844ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3845ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3846ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3847ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3848ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3849ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 38504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3851ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3852d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 38534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 38544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3855e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 38565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 38574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 38584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 38594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3860763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3861ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 38625e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 38635e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 38645e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 38655e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar starredProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 38665e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar frequentProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 38675e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 38685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 38694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 38704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 38714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3872d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 38735e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 38745e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 38754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3876d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3877d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3878d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3879763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 38804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 38814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3882d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 38835e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 38845e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 3885d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3886d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 38874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3888d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3889d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3890d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3891d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 38924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 38934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3894d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3895d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3896d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3897d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3898d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3899d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3900ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3901763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3902b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 390371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 39044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3905b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3906b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3907b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3908b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3909d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 39104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 391182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 39124da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 39134da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 39146bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 39156bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 391600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3917ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 39183653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 391982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 39204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 39214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 39223653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 39233653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 39243653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 39253653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 39264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 392782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 392889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 39292815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 39302815f58f72f109790585931f601a63ddc02536a5Evan Millar } 39312815f58f72f109790585931f601a63ddc02536a5Evan Millar 393248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 393382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 39344da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 393548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 39364da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 393748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 393848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 393948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3940ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 394182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 394289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3943ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 39444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 39454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3946a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 39475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 39485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 39495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 39505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 39515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 39527318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 39535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 39545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 39555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 39565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 39575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 39585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 39595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 39605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 39615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 39625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 39635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 39645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 39655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 39665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 39675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 39685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 39695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 3970a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 3971ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 39725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3973a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3974a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3975a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 3976ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3977ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3978ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 39794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 398082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 398189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 39824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 39834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 39844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 398548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 398682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 39874da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 39884da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 39894da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 399048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 399148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 399248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 39935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 399482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 399589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 39964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 39974da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 39984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Email.DATA + "=?"); 39994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 4000ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4001ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4002ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 40035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 400482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 400507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 400607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 400707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 400807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 400907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 401007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 401107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 40125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 401307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 401407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 401507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 401607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 401707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 401807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 401907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 402007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 402107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 402207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 402307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.DATA1 + " LIKE "); 402407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 402520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 402620938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 402720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 402807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 402907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov /* 403007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * Using a UNION instead of an "OR" to make SQLite use the right 403107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * indexes. We need it to use the (mimetype,data1) index for the 403207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * email lookup (see above), but not for the name lookup. 403307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * SQLite is not smart enough to use the index on one side of an OR 403407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * but not on the other. Using two separate nested queries 403507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * and a UNION between them does the job. 403607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov */ 403707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 403807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " UNION SELECT " + Data._ID + 403907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 404007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 404107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN "); 40427318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 404320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 40445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 40455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4046a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 40475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 40485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 4049a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4050a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4051a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 40525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 40535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 40545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 4055ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 405682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 405789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 405889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 4059ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4060ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4061ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 406248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 406382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 40644da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 406548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 406648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 40674da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 406848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 406948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 407048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 40715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 4072763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 40734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 40744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 40754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 40765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 40775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 4078763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 40794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 40804da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 40814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 40824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 40834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 40845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 40855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 408682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 40874da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 40884da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 4089e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4090e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4091e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 4092e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 409382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 4094e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4095e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4096e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 40974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 409882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 40994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 41004da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 4101a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 4102a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 4103a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 4104a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 41054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4106a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 4107a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 4108a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 4109e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 4110a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4111a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4112e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 4113b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 4114e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 4115e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 4116e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 4117e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 4118e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 4119a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 4120a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4121a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4122ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 4123b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4124ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 412589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4126ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4127ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4128ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4129ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 4130b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4131ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 41324da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 41334da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 4134ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4135ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4136ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4137ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 4138b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 4139ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 414089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 414189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 4142ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4143ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4144ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4145b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 41460c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 4147b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 4148b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 4149b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4150b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 415131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 4152d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 41532d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 41542d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 41552d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 41562d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 415731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 4158d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 4159d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 416031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 416131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 416231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 416331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4164763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 41657581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 41667581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 41672d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 416831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 416931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4170eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 4171eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 4172eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 417389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4174e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4175e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 4176e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 4177b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 4178e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 417982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4180b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 4181e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4182e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 418382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4184b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 4185e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4186e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4187e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4188eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 4189eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 4190eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 419182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 41920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 41935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 41945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 41955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 419682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 41970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 41984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 41994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 42005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 42015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 42025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 4203c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 4204a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 4205c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4206c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4207c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 42082d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 42092d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill return mGlobalSearchSupport.handleSearchShortcutRefresh(db, lookupKey, projection); 4210c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4211c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 42121b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 4213b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 42141b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 42151b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 42161b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 42171b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 4218b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 42191b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 42201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 42211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 42221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 42231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 4224b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 42251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 42261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 42271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 42281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 42291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 4230b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 42311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 423271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 42331b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 42341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 42351b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 423646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 423746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 423846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 423946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 424046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 424146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 424246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 424346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 42444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 42454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 424646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 424746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 424846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 42494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 4250f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 4251c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 42524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 42534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 42545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 42555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 42585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 42595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 4260038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 4261038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 4262038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 4263038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 42645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 42655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 42664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 42674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 42684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 42694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 42704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 42714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 42722d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 42732d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill * Returns the contact Id for the contact identified by the lookupKey. Robust against changes 42742d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill * in the lookup key: if the key has changed, will look up the contact by the name encoded in 42752d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill * the lookup key. 42762d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 42772d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 42785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 42795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 42805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 42825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 42835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 42845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 42875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 42905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 42915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 42935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 42945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 42955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 42965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 42975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 42985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 43005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 43015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 43025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 43035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 43065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 43075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 43085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 43095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 43105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 43115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 43125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 43165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 43175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 43205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 43215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 43225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 43235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 43245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 43255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 43265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 43275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 43305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 43315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 43335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 43345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 43355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 43365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 43375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 43385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 43395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 43405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 43415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 43425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 43435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 43445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 43455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 43465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 43475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 43515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 43525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 43555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 43585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 43595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 43615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 43625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 43635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 43645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 43655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 43665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 43685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 43695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 43705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 43715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 43745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 43755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 43765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 43775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 43785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 43795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 43805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 43845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 43855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 43885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 43895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 43905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 43915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 43925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 43935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 43945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 43955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 43985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 43995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 44005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 44015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 44025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 44035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 44045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 44055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 44065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 44075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 44085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 44095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 44105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 44115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 44125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 44135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 44145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 44155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 44165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 44205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 44215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 44235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 44245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 44265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 44275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 44285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 44295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 44305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 44315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 44325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 44335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 44345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 44355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 44365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 44375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 44385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 44395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 44405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 44415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 44425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 44435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 44445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 44455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 44465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 44475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 44485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 44505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 44515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 44555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 44565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 44575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 44585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4461763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 4462763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 446382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4464763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4465f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4466763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4467763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4468d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4469763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4470763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 4471b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 447282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 447382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 447482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 447582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4476b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 447782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 447882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 447982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 448082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 448182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 44823296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 44833296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 4484a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 44853296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 448682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 448782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 448882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 448982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4490ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 4491763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 4492763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 4493763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4494f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4495763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4496763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4497d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4498763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4499763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 4500763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 4501763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 4502763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 4503763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4504763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 450546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 450646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana // Note: currently, "export only" equals to "restricted", but may not in the future. 450746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana boolean excludeRestrictedData = readBooleanQueryParameter(uri, 450846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.FOR_EXPORT_ONLY, false); 450946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 4510f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 451146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 451246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana if (requestingPackage != null) { 451346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana excludeRestrictedData = excludeRestrictedData 451446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 451546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 451646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 451746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setProjectionMap(sRawContactsEntityProjectionMap); 451846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 451946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 452046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 452182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 452282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 452382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4524d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa // Note: currently, "export only" equals to "restricted", but may not in the future. 4525763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = readBooleanQueryParameter(uri, 4526d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa Data.FOR_EXPORT_ONLY, false); 4527763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4528f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4529763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4530763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4531763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar excludeRestrictedData = excludeRestrictedData 4532d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4533763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4534763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4535763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getDataView(excludeRestrictedData)); 453682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 453782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 45383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated presence when requested 4539b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 454082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 45413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 454282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 454382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 454482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 45453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated status updates when requested 4546b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 454782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 454882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 454982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 455082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 455182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 45523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 45533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 455482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 45553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 4556ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 45573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 45583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual presence when requested 45593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 45603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 45613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdates.DATA_ID + "=" 45623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 45633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 45643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 45653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual status updates when requested 45663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, 45673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS, 45683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_RES_PACKAGE, 45693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_ICON, 45703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_LABEL, 45713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_TIMESTAMP)) { 45723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 45733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 45743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 45753296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 45763296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 457782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 457882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 457982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 4580ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 4581ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 45820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 45830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 45840a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4585b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 45860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 45870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4588b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 45890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 45900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 45910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 45920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 45930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4594b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 45950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 45960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 45970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 45980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 45990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 46000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 46010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 46020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 46030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 46040a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setTables(sb.toString()); 46050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 46060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 46070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 46084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 4609f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 4610f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 4611e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4612e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 4613e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 4614e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 4615e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey throw new IllegalArgumentException("Must specify both or neither of" 4616e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + " ACCOUNT_NAME and ACCOUNT_TYPE"); 4617e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4618e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4619e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 4620e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 4621e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 4622e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 46234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 46244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 46254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 46264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 46274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 46284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 46294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 46304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 46314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4632e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 4633f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 4634f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 4635e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4636e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 4637e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 4638e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 4639e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey throw new IllegalArgumentException("Must specify both or neither of" 4640e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + " ACCOUNT_NAME and ACCOUNT_TYPE"); 4641e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4642e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4643e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 4644e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 4645e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 4646e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 4647e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 4648e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4649e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 4650e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 4651e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 4652e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 4653e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 4654e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 4655e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4656e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 4657e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 4658e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 4659e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4660e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4661e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 46627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 4663c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 4664c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 4665c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 4666c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 4667c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 4668f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 4669f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String limitParam = getQueryParameter(uri, "limit"); 4670c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 4671c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4672c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4673c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 4674c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 4675c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 4676c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 4677c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4678c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4679c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4680c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 4681c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 4682c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4683c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4684c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4685c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4686c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 46875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 46885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 46895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 46905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 46915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 46925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 46935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 46945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 46955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 46965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 46975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 46985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 46995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 47005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 47015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 47025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 47035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 47045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 47055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 47065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 47075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 47085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 47095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 47105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 47115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 47125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 47135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 47145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 47155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 47165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 471700ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 4718d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 471970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 472070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 4721fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0"; 472270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 472370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 472470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 472570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 4726d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 472770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 472867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 47295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 47305ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 4731619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4732619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4733619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4734b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 4735b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 4736b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 4737b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 4738d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 4739b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 4740b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 4741b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4742b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4743b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 4744b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 4745b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 47464da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=?"; 4747b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 47484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, 47494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 4750d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4751d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4752f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 4753d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 4754d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 475514b8a1243ab5c043b35e47527ca1c962064f3771Daisuke Miyakawa final String selection = Contacts._ID + "=" + contactId; 4756d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4757d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 4758d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 4759d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 4760d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 4761d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey outputRawContactsAsVCard(localStream, selection, null); 4762d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 4763d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4764b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4765b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 4766b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("No file at: " + uri); 4767b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4768b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4769b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4770d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 4771d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String VCARD_TYPE_DEFAULT = "default"; 4772d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4773d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4774d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 4775d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 4776d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4777d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 4778d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 4779d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 4780d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 4781d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4782d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 4783d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 4784d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4785d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 4786d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 4787d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 4788b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4789d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 4790d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 4791d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 4792d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4793d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 4794d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4795d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4796d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4797d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 4798d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 4799d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 4800d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4801d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 4802d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 4803d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 4804d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final VCardComposer composer = new VCardComposer(context, VCARD_TYPE_DEFAULT, false); 4805d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 4806d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4807f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 4808d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.init(selection, selectionArgs)) 4809d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 4810d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4811d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 4812d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 4813d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 4814d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4815d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4816d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 4817d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4818b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 48194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 48204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4821a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 48224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4823b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4824be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 48252d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 4826b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4827b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4828b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4829f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 4830f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 4831b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4832be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4833b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4834b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4835508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4836b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 483748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 483848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 483948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 484048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 484148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 484248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 484348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 484448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 484548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 484648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 484748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 484848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4849b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4850b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4851b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4852b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4853b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4854b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4855b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4856b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4857c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4858c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4859c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4860c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 486161efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 486261efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 48634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 48665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void setDisplayName(long rawContactId, int displayNameSource, 48675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary, String displayNameAlternative, String phoneticName, 48685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int phoneticNameStyle, String sortKeyPrimary, String sortKeyAlternative) { 48695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(1, displayNameSource); 48705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 2, displayNamePrimary); 48715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 3, displayNameAlternative); 48725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 4, phoneticName); 48735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(5, phoneticNameStyle); 48745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 6, sortKeyPrimary); 48755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 7, sortKeyAlternative); 48765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(8, rawContactId); 487725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 48783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 48793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 488073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 488173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 488273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 488373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 4884a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.add(rawContactId); 488573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 488673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4887c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4888c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 4889c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 4890c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4891c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4892c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4893653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 4894c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 4895653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 4896653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 4897c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 4898c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4899c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 4900c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4901c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 4902c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 4903c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4904c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4905c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4906653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 4907c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 4908653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 4909653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 4910c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 4911c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4912ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4913f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 4914f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 4915f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4916f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4917f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4918f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); 4919f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (tokens.length == 0) { 4920f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4921f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4922f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4923f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String address = tokens[0].getAddress(); 4924f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int at = address.indexOf('@'); 4925f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (at != -1) { 4926f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov address = address.substring(0, at); 4927f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4928f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4929f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4930f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 4931f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4932f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4933f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4934f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 4935f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4936f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 4937f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 4938f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4939f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4940f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4941f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4942f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 4943f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4944f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4945a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 4946a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 4947a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 4948a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4949a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 4950a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4951a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 4952a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4953a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 4954a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4955a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4956f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4957f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name) { 4958f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name); 4959f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4960f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4961315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private interface NicknameLookupPreloadQuery { 4962315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 4963315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4964315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String[] COLUMNS = new String[] { 4965315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov NicknameLookupColumns.NAME 4966315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov }; 4967315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4968315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int NAME = 0; 4969315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4970315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4971315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov /** 4972315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * Read all known common nicknames from the database and populate a Bloom 4973315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * filter using the corresponding hash codes. The idea is to eliminate most 4974315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * of unnecessary database lookups for nicknames. Given a name, we will take 49753684089aba82df3f7a0c111e7c96ed8b0380e57aDmitri Plotnikov * its hash code and see if it is set in the Bloom filter. If not, we will know 4976315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * that the name is not in the database. If it is, we still need to run a 4977315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * query. 4978315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * <p> 4979315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * Given the size of the filter and the expected size of the nickname table, 4980315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * we should expect the combination of the Bloom filter and cache will 4981315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * prevent around 98-99% of unnecessary queries from running. 4982315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov */ 4983315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private void preloadNicknameBloomFilter() { 4984315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov mNicknameBloomFilter = new BitSet(NICKNAME_BLOOM_FILTER_SIZE + 1); 4985315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4986315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupPreloadQuery.TABLE, 4987315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov NicknameLookupPreloadQuery.COLUMNS, 4988315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov null, null, null, null, null); 4989315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov try { 4990315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int count = cursor.getCount(); 4991315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov for (int i = 0; i < count; i++) { 4992315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov cursor.moveToNext(); 4993315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String normalizedName = cursor.getString(NicknameLookupPreloadQuery.NAME); 4994315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int hashCode = normalizedName.hashCode(); 4995315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov mNicknameBloomFilter.set(hashCode & NICKNAME_BLOOM_FILTER_SIZE); 4996315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4997315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } finally { 4998315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov cursor.close(); 4999315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 5000315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 5001315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 5002315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 5003f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5004f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Returns nickname cluster IDs or null. Maintains cache. 5005f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5006f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 5007315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int hashCode = normalizedName.hashCode(); 5008315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov if (!mNicknameBloomFilter.get(hashCode & NICKNAME_BLOOM_FILTER_SIZE)) { 5009315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov return null; 5010315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 5011315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 5012f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SoftReference<String[]> ref; 5013f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 5014f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 5015f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (mNicknameClusterCache.containsKey(normalizedName)) { 5016f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = mNicknameClusterCache.get(normalizedName); 5017f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (ref == null) { 5018f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return null; 5019f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5020f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = ref.get(); 5021f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5022f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5023f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5024f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (clusters == null) { 5025f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = loadNicknameClusters(normalizedName); 5026f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = clusters == null ? null : new SoftReference<String[]>(clusters); 5027f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 5028f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNicknameClusterCache.put(normalizedName, ref); 5029f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5030f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5031f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 5032f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5033f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5034315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private interface NicknameLookupQuery { 5035315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 5036315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 5037315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String[] COLUMNS = new String[] { 5038315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov NicknameLookupColumns.CLUSTER 5039315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov }; 5040315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 5041315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int CLUSTER = 0; 5042315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 5043315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 5044f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] loadNicknameClusters(String normalizedName) { 5045b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 5046f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 5047f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupQuery.TABLE, NicknameLookupQuery.COLUMNS, 5048f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.NAME + "=?", new String[] { normalizedName }, 5049f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov null, null, null); 5050f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov try { 5051f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int count = cursor.getCount(); 5052f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (count > 0) { 5053f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = new String[count]; 5054f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov for (int i = 0; i < count; i++) { 5055f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.moveToNext(); 5056f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters[i] = cursor.getString(NicknameLookupQuery.CLUSTER); 5057f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5058f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5059f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } finally { 5060f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.close(); 5061f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5062f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 5063f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5064f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5065f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 5066f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5067f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 5068f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 5069f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5070f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5071f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5072f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 5073f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 5074f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 5075f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5076f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5077f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5078f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 5079f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return ContactsProvider2.this.getCommonNicknameClusters(normalizedName); 5080f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5081f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5082f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5083f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5084f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 5085f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5086f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 50875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(1, rawContactId); 50885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(2, dataId); 50895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(3, lookupType); 50905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mNameLookupInsert, 4, name); 5091f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 5092f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5093f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5094f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5095f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 5096f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5097f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 50985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupDelete.bindLong(1, dataId); 5099f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 5100f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5101f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 51022d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 5103d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5104d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 5105d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 5106d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 5107d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 5108d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 5109d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 5110e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 5111d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN(" 5112d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 5113d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 5114d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NICKNAME + "," 5115d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.ORGANIZATION + "))"); 5116e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 5117e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 51185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 5119c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 51207318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam); 5121c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 5122c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5123c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 51247318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam) { 51257318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), true); 51265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 51275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 51285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 51297318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov boolean allowEmailMatch) { 5130d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5131dc947a9d03279eab0fb7c3b9d8ffbb492c1e2062Dmitri Plotnikov "SELECT " + NameLookupColumns.RAW_CONTACT_ID + 5132d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5133d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 5134d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 51355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 5136a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 5137a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 5138a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 513920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov + NameLookupType.ORGANIZATION); 514020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 514120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 514220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 51437318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov sb.append("))"); 5144ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5145ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 51464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 51474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 51484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 51494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 5150b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 5151b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 5152b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 5153b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 5154b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 51554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 51564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 5157b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 5158b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5159b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5160caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 51615e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 51625e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 51635e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 51645e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 51655e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 51665e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 51675e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 51685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 51695e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 51705e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 51715e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5172caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 5173caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 5174caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 5175df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 5176df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 5177caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 5178caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 5179caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5180caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 51816f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 5182caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 51836f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 5184caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5185f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5186627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov protected boolean isWritableAccount(Account account) { 5187627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 5188627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 5189627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 5190627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 5191627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov account.type.equals(sync.accountType)) { 5192627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov return sync.supportsUploading(); 5193627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5194627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5195627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 5196627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 5197627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5198627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov return false; 5199627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5200b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 5201f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 5202f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 5203f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5204f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 5205f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5206f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5207f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5208f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5209f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5210f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 5211f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5212f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5213f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5214f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5215f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 5216f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5217f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 5218f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 5219f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5220f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5221f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 5222f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 5223f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 5224f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 5225f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 5226f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5227f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5228f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 5229f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 5230f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 5231f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 5232f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5233f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5234f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5235f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5236f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5237f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 5238f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 5239f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5240f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 5241f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 5242f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 5243f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 5244f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5245f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5246f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5247f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5248f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 5249f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5250f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 5251f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5252f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5253f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5254f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 5255f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 5256f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 5257f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5258f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5259f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5260f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 5261f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 5262f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 5263f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 5264f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 5265f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5266f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5267f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 5268f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 52695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 52705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindString(SQLiteStatement stmt, int index, String value) { 52715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 52725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 52735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 52745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindString(index, value); 52755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 52765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 52775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 52785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindLong(SQLiteStatement stmt, int index, Number value) { 52795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 52805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 52815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 52825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindLong(index, value.longValue()); 52835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 52845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 52854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 5286