ContactsProvider2.java revision 2526f94e532ac973c846db0099f94b375a23be93
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.PhoneColumns; 32b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 33b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 34b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 35b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 36b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 37b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 38a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Lists; 39a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Maps; 40a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Sets; 413de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 42b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 43caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 445b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 45c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 46568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 47568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 486ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 4935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 52627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.IContentService; 53568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 543d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 55627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 5667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 573de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.content.SharedPreferences.Editor; 58b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 594cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Taoimport android.content.res.Configuration; 601129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikovimport android.database.CharArrayBuffer; 614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 62ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.CursorWrapper; 63ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 64a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 65b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 68c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 706ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 71d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 72b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 730e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 74d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 757a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawaimport android.pim.vcard.VCardConfig; 763d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 77508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 783de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 793de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.LiveFolders; 803de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.OpenableColumns; 813de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.SyncStateContract; 82b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 83ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 843de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 853de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.DisplayNameSources; 875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.FullNameStyle; 883de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 893de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.PhoneticNameStyle; 913de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 92916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 933de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 9482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 96ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 97ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 1003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 101de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 102b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 1034097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 10467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 105a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 106a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 107c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 109d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 110b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 111d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 112d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 1137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 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 322916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 323916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 324916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 325916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 326916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NICKNAME + "," + 327916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_SHORTHAND + "," + 328916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.ORGANIZATION; 329916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 330916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 331038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 332038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 333e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 335916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 336916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final HashMap<String, String> sContactsProjectionWithSnippetMap; 337916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 3385e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 3395e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentStarredProjectionMap; 3405e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentFrequentProjectionMap; 341f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 342f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final HashMap<String, String> sContactsVCardProjectionMap; 343ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 344d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 34546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** Contains the columns from the raw contacts entity view*/ 34646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final HashMap<String, String> sRawContactsEntityProjectionMap; 3474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3519261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 352e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 353ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 354ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 355ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 356ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 357373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 358b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 359eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 360eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 36182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 36282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 3631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 3679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 3689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 3699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 3709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 3719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 3722526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 3732526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 374c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 375c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 377c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 3783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 37925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 38082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 381a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 382f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 383f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 384a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 385a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 386a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 3870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 388a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 389f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov private SQLiteStatement mResetNameVerifiedForOtherRawContacts; 390a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 391f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 392f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 3931129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdStructuredName; 3941129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdOrganization; 3951129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdNickname; 3961129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdPhone; 397f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 3981129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 3991129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 4002526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 4012526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 402f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 403f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 4044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 4054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 406a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 407d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 408d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 409d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 4103653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 4113653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 4122d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 4132d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 4143653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 4155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 4165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 4175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 418f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 4195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 420ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 421ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 4225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 4233653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4245ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4255ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 42746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 42846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 42946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 430b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 433ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 43448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 436ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 43848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 442ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 44348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 445ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 446ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 447ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 448ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 44935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 450b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 451b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 45235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 453a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 454b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 455b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 456b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 457b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 459eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 460eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 46182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 46282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 4631f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 464c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 465c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 466c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 467c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 4682d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 469c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 470c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4711b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4721b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 4751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 4761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 4771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 4781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 47919a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 48019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 48119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 482038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 483038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 484e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 4864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 4875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME_PRIMARY); 4885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 4895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 4905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 4915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 4925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 4935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 4945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, Contacts.SORT_KEY_ALTERNATIVE); 4954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 5004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 501f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 5024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 504f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 5053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 5063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 5073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 5083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 5093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 5103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 5113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 5123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 5133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 5143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 5153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 5163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 5173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 5183296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 519916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap = new HashMap<String, String>(); 520916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.putAll(sContactsProjectionMap); 521916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_MIMETYPE, 522916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov SearchSnippetColumns.SNIPPET_MIMETYPE); 523916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA_ID, 524916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA_ID); 5259c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA1, 5269c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA1); 5279c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA2, 5289c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA2); 5299c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA3, 5309c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA3); 5319c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA4, 5329c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA4); 533916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5345e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5355e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5365e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Long.MAX_VALUE + " AS " + TIMES_CONTACED_SORT_COLUMN); 5375e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5385e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5395e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5405e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Contacts.TIMES_CONTACTED + " AS " + TIMES_CONTACED_SORT_COLUMN); 5415e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 542f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap = Maps.newHashMap(); 543f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 544d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 545ba355248c255551bc65d8023b968513cbe9bcdf3Jeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "NULL AS " + OpenableColumns.SIZE); 5464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 5484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 5494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 5554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 5565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_PRIMARY, 5575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY); 5585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, 5595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE); 5605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_SOURCE, 5615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE); 5625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.PHONETIC_NAME, 5635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME); 5645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.PHONETIC_NAME_STYLE, 5655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE); 566f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.NAME_VERIFIED, 567f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov RawContacts.NAME_VERIFIED); 5685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SORT_KEY_PRIMARY, 5695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY); 5705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SORT_KEY_ALTERNATIVE, 5715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE); 5724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 5734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 5744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 5754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 5764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 5774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 5784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 5794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 5804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 5814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 5824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 5832815f58f72f109790585931f601a63ddc02536a5Evan Millar 5844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 5854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 5864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 5874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 5934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 5944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 5954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 5964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 5974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 5984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 5994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 6004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 6014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 6024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 6034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 6044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 6054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 6064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 6074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 6084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 6094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 6104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 61182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 6124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 6134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 6144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 6154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 6164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 617f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov sDataProjectionMap.put(RawContacts.NAME_VERIFIED, RawContacts.NAME_VERIFIED); 61856d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 6194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 6205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 6215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 6225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 6235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 6245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 6255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 6265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, Contacts.SORT_KEY_ALTERNATIVE); 6274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 6284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 6294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 6304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 6314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 6324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 633a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 6344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 635a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 63646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana HashMap<String, String> columns; 63746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns = new HashMap<String, String>(); 63846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts._ID, RawContacts._ID); 63946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 64046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 64146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 64246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 64346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.VERSION, RawContacts.VERSION); 64446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 64546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DELETED, RawContacts.DELETED); 646bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey columns.put(RawContacts.IS_RESTRICTED, RawContacts.IS_RESTRICTED); 64746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 64846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 64946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 65046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 651f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov columns.put(RawContacts.NAME_VERIFIED, RawContacts.NAME_VERIFIED); 65246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 65346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.MIMETYPE, Data.MIMETYPE); 65446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA1, Data.DATA1); 65546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA2, Data.DATA2); 65646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA3, Data.DATA3); 65746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA4, Data.DATA4); 65846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA5, Data.DATA5); 65946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA6, Data.DATA6); 66046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA7, Data.DATA7); 66146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA8, Data.DATA8); 66246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA9, Data.DATA9); 66346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA10, Data.DATA10); 66446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA11, Data.DATA11); 66546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA12, Data.DATA12); 66646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA13, Data.DATA13); 66746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA14, Data.DATA14); 66846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA15, Data.DATA15); 66946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC1, Data.SYNC1); 67046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC2, Data.SYNC2); 67146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC3, Data.SYNC3); 67246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC4, Data.SYNC4); 67346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 67446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.STARRED, Data.STARRED); 67546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 67646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 67746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 67846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 67946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana sRawContactsEntityProjectionMap = columns; 68046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 6813296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 6823296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 6833296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 6843296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 6853296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 6863296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 6873296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6883296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6893296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6903296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 6913296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6923296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 6933296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 6943296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6953296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 6963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.PRESENCE, 6973296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 6983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS, 6993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 7003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 7013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 7033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_LABEL, 7053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_ICON, 7073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 7083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 7105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 7115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 7125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 7135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 7145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 7155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 7165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 7175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 7185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 7195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 7205e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 7215e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 7225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 7235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 7245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 7255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 7265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 7275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 7285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 7295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 7305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 7315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 7325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 7335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 7345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 7355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 7365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 7375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 7388f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 7395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 7405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 7415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 7425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 7435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 7445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 7455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 7465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, 7475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.SORT_KEY_ALTERNATIVE); 7485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 7495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 7505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 7515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 7525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 7535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 754a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 7555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 7565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 7575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 7583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 7593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 7603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 7613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 7623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 7633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 7643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 7663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 7683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 7703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 7713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 7733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 7743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 7753296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS, 7763296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 7773296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 7783296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7793296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 7803296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7813296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 7823296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7833296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 7843296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 7853296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 786e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 787e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 788fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts._ID 789fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup._ID); 79056d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 791fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LOOKUP_KEY 792fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.LOOKUP_KEY); 793e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 794fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.DISPLAY_NAME 795fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.DISPLAY_NAME); 796e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 797fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LAST_TIME_CONTACTED 798e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 799e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 800fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.TIMES_CONTACTED 801fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.TIMES_CONTACTED); 802e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 803fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.STARRED 804fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.STARRED); 805e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 806fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.IN_VISIBLE_GROUP 807fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 808e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 809fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.PHOTO_ID 810fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.PHOTO_ID); 811e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 812fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.CUSTOM_RINGTONE 813fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.CUSTOM_RINGTONE); 814e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 815fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.HAS_PHONE_NUMBER 816fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 817e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 818fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.SEND_TO_VOICEMAIL 819e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 820e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 821e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 822e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 823e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 824e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 825e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 8269261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 827ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 828ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 82989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 830035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 831035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 8329261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 8339261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 8349261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 83589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 836ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 83767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 838ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 8393cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 84094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 8413cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 84238446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 84389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 84489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 84589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 84689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 847ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 848ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 8496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 850ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 851ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 852d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 853d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 854ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 855ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 856ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 857d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 858d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 859ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 860f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 861ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 862ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 863b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 864b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 865b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 866b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 8670c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 8680c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 869b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 870b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 871eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 872eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 873eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 874eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 875eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 876eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 877341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 878341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 879341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 880fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 881341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 882341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 883341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 88468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 88568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 88668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 88768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 88868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 889e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 89068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 89168936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 89268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 893eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 894eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 895373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 8964dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 8970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 8980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 89982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 90082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 90182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 90270c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 90370c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 90482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 90582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 90682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 90782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 9080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 9090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 9100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 9110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 9120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 91382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 91419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 9151b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 9161b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 9171b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 9181b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 9191b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 9201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 9211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 9221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 9231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 9241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 9254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 9264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 9273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 9283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey map.put(toField, fromField + " AS " + toField); 9293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 9303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 9313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 9333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 9353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 937653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 9383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9391129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov @SuppressWarnings("all") 9403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 9413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 942a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 943a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 944a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 945a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 946a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 947a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 948a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 949a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 9503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 952653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 953653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 954b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 955653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 956653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 957653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 958653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 9593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 9613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 963e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 964e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 965e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 966e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 967653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 968e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 969e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 970e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 9713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 9753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 9763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 977653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 978f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 97914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 98014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 981653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 982653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 983653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 984653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 985653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 986653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 987653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 988653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 989653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 990653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 991653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 992653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 993653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 994653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 995653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 996653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 997653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 9984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 9994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " =?", mSelectionArgs1); 1000653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1001653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1002f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1003653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 1004653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 10053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 100814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 100914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 101014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 10114da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10124da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=?", mSelectionArgs1); 10134da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 10144da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=?", mSelectionArgs1); 10153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 10165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 10173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 10193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 10224da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov long mimeTypeId = getMimeTypeId(); 1023e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 1024e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 10254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 10264da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = db.query(DataDeleteQuery.TABLE, 10274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov DataDeleteQuery.CONCRETE_COLUMNS, 10284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Data.RAW_CONTACT_ID + "=?" + 10294da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov " AND " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId, 10304da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 10313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 1032e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 103314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 1034f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 1035e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 1036e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 1037e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 1038e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 10393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 10413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 10423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (primaryId != -1) { 10444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov setIsPrimary(rawContactId, primaryId, mimeTypeId); 10454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 1046e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1047e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1048e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 1049e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 1050e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 1051e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 1052e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1053e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 10543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 105625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 1057285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1058d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(db, rawContactId); 1059fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(db, rawContactId); 1060285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 10613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1062a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1063a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1064a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return true; 1065a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1066622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1067622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1068622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 1069622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * as baseline, but augmented with any updates. 1070622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1071622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 1072622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 1073622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 10744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=?", 10764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 1077622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 1078622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 1079622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 1080622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 1081622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.put(key, cursor.getString(i)); 1082622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1083622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1084622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 1085622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 1086622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1087622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 1088622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 1089622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 10933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 10953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1100622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 11013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1102622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 11033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1104622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 11053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1109622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 111014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 111114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 111214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1113f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1114d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov Integer fullNameStyle = values.getAsInteger(StructuredName.FULL_NAME_STYLE); 1115d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name, 1116d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov fullNameStyle != null ? fullNameStyle : FullNameStyle.UNDEFINED); 111725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 111814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 111914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 112014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 112114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 112214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1123f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1124622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1125622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1126cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1127622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1128622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 112914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1130f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 113114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1132f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 1133f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1134f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1135d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov Integer fullNameStyle = values.getAsInteger(StructuredName.FULL_NAME_STYLE); 1136d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name, 1137d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov fullNameStyle != null ? fullNameStyle : FullNameStyle.UNDEFINED); 113814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 113925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 114014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 114114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 114214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 114314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 114414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 114514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 114614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 114714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 114814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1149f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 115025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 115114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 11523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1155622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 11563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1157622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1158622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1159622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1160622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 11613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1162622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1163622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1164622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1165622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1166622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1167622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1168622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 116967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1170622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 117167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 117267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1173622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1174622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 11758c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1176622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1177622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 117867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 117967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 118067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 118167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 118267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 118367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 11848c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1185622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 11864cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao // As the name could be changed, let's guess the name style again. 11874cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao name.fullNameStyle = FullNameStyle.UNDEFINED; 11884cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mSplitter.guessNameStyle(name); 11895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 11905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov final String joined = mSplitter.join(name, true); 1191622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 11925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 11935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov update.put(StructuredName.FULL_NAME_STYLE, name.fullNameStyle); 11945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, name.phoneticNameStyle); 11954cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } else if (touchedUnstruct && touchedStruct){ 1196d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov if (!update.containsKey(StructuredName.FULL_NAME_STYLE)) { 1197d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov update.put(StructuredName.FULL_NAME_STYLE, 1198d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mSplitter.guessFullNameStyle(unstruct)); 11994cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1200d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov if (!update.containsKey(StructuredName.PHONETIC_NAME_STYLE)) { 1201d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, 1202d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mSplitter.guessPhoneticNameStyle(unstruct)); 12034cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1204622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1205622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1206622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1207622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1208622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1209622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1210622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1211622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1212622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1213622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1214622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1215622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1216622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1217622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1218622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1219622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1220622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1221622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1222622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1223622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1224f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1225622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1226622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1227622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1228f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1229622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1230622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1231622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1232622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1233622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1234622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1235622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1236622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1237622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1238622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1239622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1240622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1241622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1242622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1243622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1244622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1245622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1246622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 124767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 124867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 124967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 125067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1251622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1252622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1253622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1254622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1255622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1256622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 125767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 125867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 125967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1260622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1261622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1262622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 12633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 12683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 12703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 12713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 12733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 12743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 12753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 12763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1280622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1281622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1282622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1284622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1285622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1286f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1287622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1288622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1289622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1290f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1291622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1293622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1294622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1295622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1296622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1297622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1298622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1299622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1300622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 13013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1302622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1303622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1304622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1305622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1306622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 13113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 13133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 13143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13175ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1318a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1319a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1320a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1321a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1322a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 132325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1324a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1325a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 13263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 132914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1330f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1331a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 133214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 133314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1334f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 133514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 133631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov boolean containsCompany = values.containsKey(Organization.COMPANY); 133731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov boolean containsTitle = values.containsKey(Organization.TITLE); 133831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsCompany || containsTitle) { 133931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov String company; 134031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 134131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsCompany) { 134231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov company = values.getAsString(Organization.COMPANY); 134331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } else { 134431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 134531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov company = DatabaseUtils.stringForQuery(db, 134631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov "SELECT " + Organization.COMPANY + 134731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " FROM " + Tables.DATA + 134831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " WHERE " + Data._ID + "=?", mSelectionArgs1); 134931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 135031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 135131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov String title; 135231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsTitle) { 135331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov title = values.getAsString(Organization.TITLE); 135431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } else { 135531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 135631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov title = DatabaseUtils.stringForQuery(db, 135731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov "SELECT " + Organization.TITLE + 135831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " FROM " + Tables.DATA + 135931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " WHERE " + Data._ID + "=?", mSelectionArgs1); 136031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 136131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 136231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov deleteNameLookup(dataId); 136331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov insertNameLookupForOrganization(rawContactId, dataId, company, title); 136431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 136531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 136631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 136714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 136814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 136914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 137014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1371a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 137214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 137314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 137414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 137525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1376a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 137714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 137814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 137914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 138014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 13813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 13823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 13833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 13843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 13853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 13863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 13873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1389a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1390a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1391a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1392a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1393a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 13943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1396e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1397e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1398e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1399e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1400e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1401e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1402e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 14035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 140414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 140514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 140614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 140714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 140825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1409f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 141014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 141114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 141214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 141314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 141414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1415f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 141614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 141714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 141814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1419f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 142014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1421b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (values.containsKey(Email.DATA)) { 1422b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String address = values.getAsString(Email.DATA); 1423b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov deleteNameLookup(dataId); 1424b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 1425b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1426b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov } 142714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 142814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 142914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 143014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 143114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 143214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 143314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 143414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 143514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1436f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 143725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 143814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1439e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1440e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1441e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1442e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1443e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1444e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1445e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1446e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1447e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1448e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1449e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1450e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1451e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1452e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 145314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 145414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 145514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 145614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 145714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 145814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 145914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 146014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 146114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 146214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 146414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1466f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 146714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 146814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 146914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 147014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 147114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1472f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 147314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 147414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 147514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1476f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 147714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1478b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (values.containsKey(Nickname.NAME)) { 1479b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 1480b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov deleteNameLookup(dataId); 1481b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1482b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1483b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov } 148414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 148514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 148614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 148714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 148814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 148914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 149014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 149114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 149214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1493f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 149425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 149514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 149614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 149714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 149814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 14993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 15003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 15023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 15033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 15065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 15070b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 15080b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 15090b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 15100b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1511653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 15120b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1513653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 15140b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1515285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 151625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 15170b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 15180b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 15190b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1520653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1521653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1522653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1523653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1524653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1525f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 152614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 152714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 15280b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 15290b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 15300b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1531653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1532f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1533653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 15340b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1535285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 153625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 15370b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 1538f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 15390b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 154014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 154114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 154214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 154314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 154414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 154514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 154614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 154714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 154814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 154914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1550285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 155125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 155214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1553653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1554653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1555653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1556e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1557e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1558e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1559e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1560653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1561653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1562653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1563e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1564653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1565653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1566e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1567653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 15685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1569653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1570e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 157136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.MIN_MATCH, 157236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov PhoneNumberUtils.toCallerIDMinMatch(number)); 157336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov 1574653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1575653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 15764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 15774da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=?", mSelectionArgs1); 1578e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 15793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 15823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 15833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 15843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 15853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 15863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 15873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 15883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 15893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 15903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 15913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 15923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 15933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1597653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1598653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1599653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1600653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1601653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1602653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1603653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1604653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1605653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 16060be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 16070be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 16080be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1609653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1610653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1611653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1612653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1613f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 161414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1615653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1616f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 16170be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 16180be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 16190be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 16200be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 16210be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 16220be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 16230be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 16240be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 16250be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 16260be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 16270be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 16280be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1629b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 16300be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1631b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 16320be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1633653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1634653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1635653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1636653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1637653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1638653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1639653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1640653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1641653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1642653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1643653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1644653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1645653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1646653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1647653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1648653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1649653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1650653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1651653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1652653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1653653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1654653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1655653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1656653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1657ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId, 1658ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.get(rawContactId)); 1659653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1660653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1661653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1662653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1663a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1664a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1665a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1666a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1667a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1668653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1669653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1670a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1671a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1672a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1673a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1674a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1675a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1676a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1677a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1678a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1679285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1680285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1681285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1682a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1683a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1684a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1685a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1686a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1687f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1688a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1689f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1690a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1691a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1692a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1693a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1694a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1695a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1696a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1697a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1698a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1699a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1700a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1701a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1702a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1703a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1704a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1705a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1706a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1707ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov /** 1708ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 1709ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1710ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1711ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov public class GroupIdCacheEntry { 1712ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1713ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 1714ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1715ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1716ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1717a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 17183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 1719b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 172031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 17214097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1722f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1723315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1724622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1725622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1726ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1727ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1728ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // is a list of groups with this group id. 1729ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1730ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 1731622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1732f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1733a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1734d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1735a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 173620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 17371129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private CharArrayBuffer mCharArrayBuffer = new CharArrayBuffer(128); 17385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private NameSplitter.Name mName = new NameSplitter.Name(); 173920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1740ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 174173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1742ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<Long, Account> mInsertedRawContacts = Maps.newHashMap(); 1743b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1744a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private HashSet<Long> mDirtyRawContacts = Sets.newHashSet(); 1745b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1746de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 17471a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 17481a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 174981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 175081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 17514cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 1752d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 17534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 17544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1755de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1756ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1757ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1758ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1759ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1760ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1761ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1762ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 176335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1764ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 1765de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1766b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1767a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1768b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1769d076a108d58b30591f197e1b90fa8de60999c499Dmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper); 17700e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1771a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1772b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 177304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov initForDefaultLocale(); 1774653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1775d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov mCommonNicknameCache = new CommonNicknameCache(db); 1776d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1777c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1778653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1779653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1780653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1781653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1782653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1783c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1784653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1785653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1786653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1787653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1788653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1789653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1790653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1791653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1792653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1793653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1794653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 179525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate = db.compileStatement( 179625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 17975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov " SET " + 17985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE + "=?," + 17995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY + "=?," + 18005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," + 18015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME + "=?," + 18025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE + "=?," + 18035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY + "=?," + 18045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE + "=?" + 180525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 18063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1807a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate = db.compileStatement( 1808a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.CONTACTS + 1809a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1810a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1811a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1812a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1813a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1814a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1815a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1816a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1817a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1818a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 18190a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 18200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1821a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " LIMIT 1)" + 1822a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1823e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1824f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1825f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1826f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1827f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1828f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1829f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1830f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1831a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert = db.compileStatement( 1832a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1833a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 18340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 18350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 18360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 18370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 18380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 1839a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1840a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace = db.compileStatement( 1841a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1842a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 18430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 18440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 18450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 18460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 18470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 18480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1849a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1850a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp = db.compileStatement( 1851a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 18520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 18530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 1854a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 18550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 18560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 18570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate = db.compileStatement( 18580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 18590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 18600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 18610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 18620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1863a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1864a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete = db.compileStatement( 1865a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1866a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1867a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1868f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // When setting NAME_VERIFIED to 1 on a raw contact, reset it to 0 1869f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // on all other raw contacts in the same aggregate 1870f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts = db.compileStatement( 1871f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 1872f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " SET " + RawContacts.NAME_VERIFIED + "=0" + 1873f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=(" + 1874f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1875f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1876f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?)" + 1877f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " AND " + RawContacts._ID + "!=?"); 1878f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 18793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 18803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1881e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 18823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 18833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 188467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 188567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 18863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 18873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 188814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 18893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 18903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1891622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1892622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1893a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1894a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 18953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 18963d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1897568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 18983d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1899568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1900c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov verifyAccounts(); 190170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 1902f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1903f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 19041129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdStructuredName = mDbHelper.getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE); 19051129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdOrganization = mDbHelper.getMimeTypeId(Organization.CONTENT_ITEM_TYPE); 19061129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdNickname = mDbHelper.getMimeTypeId(Nickname.CONTENT_ITEM_TYPE); 19071129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdPhone = mDbHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 190804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov 19091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 19104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 19114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 191204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 19134cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 191404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov mNameSplitter = mDbHelper.createNameSplitter(); 19154cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 19164cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 19174cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 19184cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 19194cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao @Override 19204cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao public void onConfigurationChanged (Configuration newConfig) { 19214cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao if (newConfig != null && mCurrentLocale != null 192204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov && !mCurrentLocale.equals(newConfig.locale)) { 192304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov initForDefaultLocale(); 192404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov // TODO rebuild name lookup for the new locale 19254cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 19264cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1927c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 1928c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1929c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1930c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 1931c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 193231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1933de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1934b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1935b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 193631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 193731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1938013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1939013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1940013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1941013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 19425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 19435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 19445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 19455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 19465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 19473d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 19483d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 19493d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 19503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1952568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1953568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1954568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1955568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1956568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1957568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1958568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1959568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1960568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1961ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1962568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1963568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1964568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1965568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1966568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1967d076a108d58b30591f197e1b90fa8de60999c499Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1968568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1969568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1970568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1971568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1972568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1973ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1974ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1975568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1976568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1977568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1978568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1979568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1980568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1981568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1983568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1984568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 19853d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 19863d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 19873d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 19883d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 19893d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 19903d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 19913d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 19923d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19933d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19943d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 19953d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1996568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 19970e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 19983d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 19993d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 20003d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 20010e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(aggregatorEnabled); 20023d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 20033d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 20043d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 20053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 20063d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 20073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 20083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2009a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 2010a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 2011a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 2012a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 2013b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 2014a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 2015a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2016568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 2017568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 2018568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 2019568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 2020568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 2021568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 2022568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 2023568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 2024ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 2025ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 2026ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 2027ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 2028ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 2029ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 2030ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 2031ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 203281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 2033ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2034ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2035568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2036568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2037568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2038568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2039568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 2040568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2041568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 2042568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2043568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2044568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2045568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 2046568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2047568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 2048568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2049568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2050568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2051568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 2052568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2053568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 2054568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2055568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2056568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2057568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2058568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 2059568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2060568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 2061568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2062568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 20634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2064285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 2065bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2066b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 2067b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2068285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 20691ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 2070b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2071b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2072b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2073b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 2074285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 2075b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 2076df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 2077a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.clear(); 2078285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2079285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2080285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2081285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 20821129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 2083bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2084b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2085b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2086285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 2087b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 20881ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 20891a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 20901a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 2091b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 20921a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 2093b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2094b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2095b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2096bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2097b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2098b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 20991129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 210008e42c9c153a60bf2e7c71dd40bf84bb5fc93555Dmitri Plotnikov for (long rawContactId : mInsertedRawContacts.keySet()) { 2101d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(mDb, rawContactId); 2102d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mContactAggregator.onRawContactInsert(mDb, rawContactId); 2103285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2104b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2105a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov if (!mDirtyRawContacts.isEmpty()) { 2106a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2107a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2108a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mDirtyRawContacts); 2109a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2110a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2111a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2112a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2113b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 2114a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2115a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2116a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mUpdatedRawContacts); 2117a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2118a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2119b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2120b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2121b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 2122b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 21239d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana if (mDbHelper.getSyncState().update(mDb, id, entry.getValue()) <= 0) { 21249d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 21259d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 21269d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 2127b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2128b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2129b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2130b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2131b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2132a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2133a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2134a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2135a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2136a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private void appendIds(StringBuilder sb, HashSet<Long> ids) { 2137b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2138a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2139b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2140a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2141a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2142285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2143285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2144285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2145cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 214681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 214781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 214881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 214981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 215081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 215181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 215281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2153cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2154568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2155285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 2156ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return mInsertedRawContacts.containsKey(rawContactId); 2157285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2158285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 21593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 21603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 21613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 21623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 21633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 21643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 21653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 21663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 21673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 21684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2169de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2170bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 21711129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2172b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2173f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2174f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2175f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2176f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2177a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2178a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 217935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2180a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 218135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2182b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 218335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 218435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2185d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2186d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 21876bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 21886bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 21896bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 21905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2191f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertRawContact(uri, values); 2192f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2193a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2194a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2195a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 21965ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 21975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2198f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2199f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2200a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2201a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2202a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2203a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2204f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2205f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2206a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2207a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2208a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2209ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2210f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2211f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2212ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2213ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2214ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2215eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 22165aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 221743880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2218eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2219eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2220eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 222182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 222282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 22231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 22241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 22251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2226a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 222781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2228f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2229a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2230a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 22317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 22327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 22337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 22347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2235de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2236a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2237a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2238a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2239e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2240e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2241e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2242e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2243e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2244e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2245e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2246e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2247e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2248e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2249e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2250e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2251e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 22527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2253e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2254f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2255f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2256e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2257f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2258f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2259f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2260e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2261e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2262e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2263e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2264e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 2265fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2266fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 2267e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2268e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2269e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2270e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2271e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2272e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2273e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2274e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2275e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2276e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2277e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2278e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 2279fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2280fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 2281e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2282e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2283e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2284f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2285f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2286e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2287f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2288f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2289e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2290e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2291f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2292f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2293e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2294f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2295f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2296f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2297f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2298035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2299f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2300e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 23017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 23027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 23037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2304d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 23056bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 23066bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 23076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 23086bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2309d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2310de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 23116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 23126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 23136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2314a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2315a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2316f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2317f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2318a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2319a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2320f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertRawContact(Uri uri, ContentValues values) { 2321f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2322f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2323f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2324f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2325e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 23267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 23273d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 23283d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2329f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 23303d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 23313d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2332f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 2333023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 2334285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2335285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2336e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mInsertedRawContacts.put(rawContactId, account); 2337f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2338023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2339a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2340a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2341a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2342a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2343a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2344a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2345a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2346a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2347f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2348a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2349de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2350de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 235167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2352de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 235320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2354de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2355de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2356de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2357b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2358de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2359de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2360508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2361de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2362de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2363de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2364de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2365de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 23664097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2367b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2368de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2369a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2370a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2371a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2372f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2373de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2374a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2375b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2376a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2377a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2378a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2379a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2380a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 23814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 23824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 23838e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 23848e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 23858e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 23868e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 23878e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2388b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2389f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 23908e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 23918e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 23928e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 23938e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2394421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 2395f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 23968e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 23978e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 23988e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2399b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2400f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 24018e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 24028e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 24038e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2404f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 24058e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2406f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2407c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 2408b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 24098e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2410f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 24118e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2412f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2413f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2414f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2415a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 24165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 24179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 24189261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 24195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 24209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 24219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 24229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 24239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 24249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 2425ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId, 2426ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Account account) { 2427ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2428ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (account == null) { 24294da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 2430ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 24314da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov RawContacts._ID + "=?", mSelectionArgs1, null, null, null); 2432ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov try { 2433ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2434ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = c.getString(RawContactsQuery.ACCOUNT_NAME); 2435ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = c.getString(RawContactsQuery.ACCOUNT_TYPE); 2436ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 2437ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov account = new Account(accountName, accountType); 2438ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 24399261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2440ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } finally { 2441ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov c.close(); 24429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 24439261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2444ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 24459261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 24469261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 2447ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov + "has a sourceid the the contact must be associated with " 24489261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 24499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 24509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2451ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ArrayList<GroupIdCacheEntry> entries = mGroupIdCache.get(sourceId); 2452ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entries == null) { 2453ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries = new ArrayList<GroupIdCacheEntry>(1); 2454ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.put(sourceId, entries); 2455ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2456ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2457ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int count = entries.size(); 2458ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov for (int i = 0; i < count; i++) { 2459ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = entries.get(i); 2460ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entry.accountName.equals(account.name) && entry.accountType.equals(account.type)) { 2461ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 2462ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2463ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2464ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2465ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = new GroupIdCacheEntry(); 2466ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountName = account.name; 2467ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountType = account.type; 2468ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.sourceId = sourceId; 2469ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries.add(0, entry); 2470ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 24719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 24725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 2473ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 24749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2475df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 24769261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 2477ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2478ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = c.getLong(0); 24799261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 24809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2481df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2482df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 24839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 24849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 24859261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 24869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 24879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 24889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2489ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = groupId; 24909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 24919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 24929261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 24939261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2494ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2495ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 24969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 24979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2498d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private interface DisplayNameQuery { 24991129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov public static final String RAW_SQL = 25001129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov "SELECT " 25011129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + DataColumns.MIMETYPE_ID + "," 25021129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.IS_PRIMARY + "," 25031129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.DATA1 + "," 25045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA2 + "," 25055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA3 + "," 25065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA4 + "," 25075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA5 + "," 25085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA6 + "," 25095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA7 + "," 25105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA8 + "," 25115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA9 + "," 25125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA10 + "," 25135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA11 + 25141129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " FROM " + Tables.DATA + 25151129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " WHERE " + Data.RAW_CONTACT_ID + "=?" + 25161129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " AND (" + Data.DATA1 + " NOT NULL OR " + 25171129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Organization.TITLE + " NOT NULL)"; 2518d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2519d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int MIMETYPE = 0; 2520d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int IS_PRIMARY = 1; 25215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int DATA1 = 2; 25225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int GIVEN_NAME = 3; // data2 25235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FAMILY_NAME = 4; // data3 25245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PREFIX = 5; // data4 25255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int TITLE = 5; // data4 25265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int MIDDLE_NAME = 6; // data5 25275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int SUFFIX = 7; // data6 25285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_GIVEN_NAME = 8; // data7 25295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_MIDDLE_NAME = 9; // data8 25305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME = 9; // data8 25315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_FAMILY_NAME = 10; // data9 25325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FULL_NAME_STYLE = 11; // data10 25335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME_STYLE = 11; // data10 25345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_NAME_STYLE = 12; // data11 2535d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2536d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2537d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov /** 2538d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * Updates a raw contact display name based on data rows, e.g. structured name, 2539d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * organization, email etc. 2540d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov */ 2541ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 2542bca1c8b44f99528fc123d5547723e44771e8e934Mike Lockwood int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 25435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name bestName = null; 25445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestDisplayName = null; 25455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestPhoneticName = null; 25465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 2547d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 25481129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 25491129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Cursor c = db.rawQuery(DisplayNameQuery.RAW_SQL, mSelectionArgs1); 2550d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov try { 2551d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov while (c.moveToNext()) { 25521129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov int mimeType = c.getInt(DisplayNameQuery.MIMETYPE); 25535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int source = getDisplayNameSource(mimeType); 25545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source < bestDisplayNameSource || source == DisplayNameSources.UNDEFINED) { 25555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 25565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25571129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 25585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source == bestDisplayNameSource && c.getInt(DisplayNameQuery.IS_PRIMARY) == 0) { 25595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 2560d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 25611129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 25625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mimeType == mMimeTypeIdStructuredName) { 25635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name name; 25645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestName != null) { 25655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = new NameSplitter.Name(); 25665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 25675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = mName; 25685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.clear(); 25695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.prefix = c.getString(DisplayNameQuery.PREFIX); 25715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.givenNames = c.getString(DisplayNameQuery.GIVEN_NAME); 25725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.middleName = c.getString(DisplayNameQuery.MIDDLE_NAME); 25735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.familyName = c.getString(DisplayNameQuery.FAMILY_NAME); 25745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.suffix = c.getString(DisplayNameQuery.SUFFIX); 25755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.fullNameStyle = c.isNull(DisplayNameQuery.FULL_NAME_STYLE) 25765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? FullNameStyle.UNDEFINED 25775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.FULL_NAME_STYLE); 25785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticFamilyName = c.getString(DisplayNameQuery.PHONETIC_FAMILY_NAME); 25795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticMiddleName = c.getString(DisplayNameQuery.PHONETIC_MIDDLE_NAME); 25805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticGivenName = c.getString(DisplayNameQuery.PHONETIC_GIVEN_NAME); 25815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticNameStyle = c.isNull(DisplayNameQuery.PHONETIC_NAME_STYLE) 25825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 25835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.PHONETIC_NAME_STYLE); 25845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (!name.isEmpty()) { 25855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 25865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName = name; 25875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 25885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else if (mimeType == mMimeTypeIdOrganization) { 25895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 25905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 25915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 2592d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov bestDisplayNameSource = source; 25931129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 25941129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 25955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = c.getString(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME); 25965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = 25975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.isNull(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE) 25985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 25995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE); 26005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 26015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.TITLE, mCharArrayBuffer); 26025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 26031129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayNameSource = source; 26041129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 26051129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 26065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 26075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 26081129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 2609d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 26105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 26115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Display name is at DATA1 in all other types. 26125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // This is ensured in the constructor. 26135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 26145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 26155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 26165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 26175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 26185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 26195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 26205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 26215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 26225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 2623d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2624d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2625d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2626d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } finally { 2627d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov c.close(); 2628d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2629d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 26305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary; 26315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNameAlternative; 26325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyPrimary = null; 26335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyAlternative = null; 26345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int displayNameStyle = FullNameStyle.UNDEFINED; 26355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 26365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestDisplayNameSource == DisplayNameSources.STRUCTURED_NAME) { 26375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = bestName.fullNameStyle; 26385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.CJK 26395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.UNDEFINED) { 26405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 26415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName.fullNameStyle = displayNameStyle; 26425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 26435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 26445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = mNameSplitter.join(bestName, true); 26455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative = mNameSplitter.join(bestName, false); 26465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 26475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = mNameSplitter.joinPhoneticName(bestName); 26485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = bestName.phoneticNameStyle; 26495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 26505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = displayNameAlternative = bestDisplayName; 26515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 26525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 26535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticName != null) { 26545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = bestPhoneticName; 26555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticNameStyle == PhoneticNameStyle.UNDEFINED) { 26565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = mNameSplitter.guessPhoneticNameStyle(bestPhoneticName); 26575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 26585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 26595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED) { 26605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.guessFullNameStyle(bestDisplayName); 26615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED 26625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.CJK) { 26635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedNameStyleBasedOnPhoneticNameStyle( 26645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle, bestPhoneticNameStyle); 26655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 26665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 26675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 26685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.CHINESE) { 26695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = 26704cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao ContactLocaleUtils.getSortKey(displayNamePrimary, FullNameStyle.CHINESE); 26715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 26725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 26735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 26745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (sortKeyPrimary == null) { 26755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = displayNamePrimary; 26765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyAlternative = displayNameAlternative; 26775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 26785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 26795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov setDisplayName(rawContactId, bestDisplayNameSource, displayNamePrimary, 26805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative, bestPhoneticName, bestPhoneticNameStyle, 26815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary, sortKeyAlternative); 2682d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2683d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 26841129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private int getDisplayNameSource(int mimeTypeId) { 26851129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (mimeTypeId == mMimeTypeIdStructuredName) { 26861129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.STRUCTURED_NAME; 26871129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdEmail) { 26881129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.EMAIL; 26891129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdPhone) { 26901129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.PHONE; 26911129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdOrganization) { 26921129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.ORGANIZATION; 26931129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdNickname) { 26941129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.NICKNAME; 26951129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else { 26961129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.UNDEFINED; 26971129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 26981129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 26991129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 27009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 270120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 270220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2703f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 270420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 270520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2706de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2707de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 270814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2709de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2710de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 271114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 271214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2713a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2714a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2715f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 271688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 2717a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2718a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2719a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 272088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 272120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 272220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2723de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 272420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 272520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 272620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 272720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 272820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 272988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 273088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 273188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 273220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2733f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 273488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 273588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 27364da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 27374da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=?", 27384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 2739f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 274020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 274120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 274220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 274320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 274420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 274514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 274620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 274720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 274820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 274920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 275020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 275120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 275220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 275320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 275420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 27557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 275620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 275720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 275820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2759a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2760a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 27618e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2762a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2763a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2764a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 27658e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 276620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 276720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 276820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 276920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 277020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 277120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2772ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2773ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2774f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2775f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2776f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2777f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2778e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 2779ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2780ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 2781f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 278267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 2783f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 278467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 2785f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 2786ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2787f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2788f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 278973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 279073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2791f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 2792ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2793f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 27941a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2795ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2796ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2797ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2798ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2799ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 28005aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2801e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 28025aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 28031a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 28041a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2805e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 28061a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 2807e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2808e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2809e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2810ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 281182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 28121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 281382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 281482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 28150a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 28164dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 28174dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 28180a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 281982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 28204dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 28214dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 28224dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 28234dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 28241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 28251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2826dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 2827dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 282882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 2829f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 28302526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 2831dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 2832dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 2833dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 28342526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 28352526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 28361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 2837dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 2838dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 28390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 28400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 28410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 28420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2843dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 2844dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 2845dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 28462526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov String mimeTypeIdIm = String.valueOf(mMimeTypeIdIm); 2847dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 28482526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov String mimeTypeIdEmail = String.valueOf(mMimeTypeIdEmail); 2849f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2850f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 2851f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 2852f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 2853f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2854f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 2855f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 28562526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 28572526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 28582526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 28592526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 28602526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 28612526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 28622526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 28632526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 2864dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 28652526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 28662526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 2867dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 28682526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 28692526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 2870dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 28712526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 28722526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 28732526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 28742526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 28752526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 28762526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 2877dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 28782526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 28792526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 2880dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2881dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 28821f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 288382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 28842526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 28852526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 2886dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 288770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 2888f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 288970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 28901f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 28911f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2892de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 28932526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 2894c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 28951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 289667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 28975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2898e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 28991f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 29001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 29011f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 29021f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 29031f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 290431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 290531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 290631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 29071f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 29081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 290982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2910a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2911a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2912a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2913a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2914a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2915a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2916a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 291782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2918a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2919a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 292082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 292182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 292282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 292382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 292482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2925a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 292682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 292782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 29281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2929a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2930a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2931a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2932e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 29330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 293482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 293582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 29360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 29370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 29380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 29390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 29400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 29410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 29420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 29430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 29440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 29450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 29460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 29470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2948a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 2949a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 2950a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 295182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 295282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 2953a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 2954a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 29555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 3, status); 29565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 4, resPackage); 29575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 5, iconResource); 29585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 6, labelResource); 2959a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 2960a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 2961a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2962a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 2963a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 29645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 2, status); 29655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 3, resPackage); 29665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 4, iconResource); 29675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 5, labelResource); 2968a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 2969a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 2970a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 29710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 2972a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 29735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 2, status); 2974a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 29755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 4, status); 2976a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 29770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 29785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusAttributionUpdate, 1, resPackage); 29795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 2, iconResource); 29805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 3, labelResource); 29810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 29820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 2983a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2984e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2985e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2986bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2987a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2988a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 2989a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 2990a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 2991a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2992a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2993a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 29941f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 29951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 29964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2997de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2998bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2999b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 3000b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3001b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3002f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3003f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 3004508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 3005508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 300635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3007b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 300835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3009b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 3010b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3011b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3012b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3013b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 3014b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3015cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 3016cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 3017cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 3018cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3019cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3020d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3021d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3022cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 30236bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 30246bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 30259fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 30262e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 30272e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 30282e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3029fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3030fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 30312e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 30322e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 30332e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 30342e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 30352e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 30362e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 30379fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 30389fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 30399fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann long contactId = ContentUris.parseId(uri); 30409fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 30419fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 30429fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 30439fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 30449fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 30459fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 30469fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 30479fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 30489fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 30499fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 30509fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 30519fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 30529fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[1] = lookupKey; 30539fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 30549fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 30559fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann Cursor c = query(db, lookupQb, null, selection, args, null, null, null); 30569fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 30579fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 30589fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 30599fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return deleteContact(contactId); 30609fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 30619fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 30629fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 30639fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 30649fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 30659fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 30669fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 30679fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 30689fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 30699fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 30702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 30712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 3072fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, 3073fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 3074e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 30752971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 30762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 30772971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 3078fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 3079fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 3080fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 30812971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 30822971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 30832971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 30842971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 30852971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 30862971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 30872971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 30885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 30892971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 3090fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return deleteRawContact(rawContactId, mDbHelper.getContactId(rawContactId), 3091fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 3092508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3093508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 309420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3095f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 3096944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 3097f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 309820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 309920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 310048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 310148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 310248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 310348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3104508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3105f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 31064da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 31074da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 3108ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3109ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3110ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3111f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 31125aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 31132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 31142971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 31152971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 31162971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 31172971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 3118e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 31192971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 31202971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 31215aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 31222971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 31232971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 31242971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 31252971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 312681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3127f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 312881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 31292971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3130508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3131508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3132eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 313343880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3134e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3135eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3136eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 313782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 31380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 31391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31401f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 314181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 314281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 31433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 314481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3145508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 31464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 31474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 31481c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3149ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3150b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 315194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 3152de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 315394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 315494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 315594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 315694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3157f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 3158de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 315994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 316094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 316194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3162f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 3163de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 316494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 316594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 31661a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 316794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 316894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 316994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 31705aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 3171e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 31721a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3173e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3174e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3175e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3176cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 317796b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 3178cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 317996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 318096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 3181cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3182cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3183cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3184cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 3185cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3186cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3187cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3188cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3189cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3190cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3191cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3192cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3193fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 31943389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3195f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 319614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 3197fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov int count = mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 3198fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForContact(mDb, contactId); 3199fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 320033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 3201b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 3202cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 320333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 320433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 320533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 32060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 32079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 32089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 32099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 32109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 32119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 32129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 32139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 32149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 32150a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 32160a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3217cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 321881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 321981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3220cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3221cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3222cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3223cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3224cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3225cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3226cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 3227cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3228cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 32294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3230de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3231de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3232bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3233b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3234b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3235b5a4add17815167d20a90645779df34cdf45280dFred Quintana 323635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 323700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 323800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3239b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3240b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 32411129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 3242b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 3243b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3244b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3245b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3246f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3247f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 324800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 324935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3250b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3251b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3252b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3253b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3254b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3255b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3256b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3257b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3258b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3259b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3260b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 326135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3262d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 32638c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 326400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 326500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 326600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3267d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 32688c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 3269c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3270c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3271c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 32722e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 32732e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 32742e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 32752e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 32762e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3277fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3278fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 32792e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 32802e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 32812e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 32828c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 32832e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 32842e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 32852e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 32867d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 32877d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 32887d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 32897d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 32907d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 32917d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 32927d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 32937d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 32947d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 32957d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 329620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3297944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3298f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 329981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3300f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 330181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 330220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 330320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3304c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 330548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 330648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 330748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 330848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3309f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 331081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3311f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 331281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 331300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 331400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 33157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 33165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 33175ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 33184529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 33197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 33207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 33217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 33225ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 332333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 33244529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 33254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 33264da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 33274529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 33284529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 33294da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 33304da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1); 33314529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 33327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 33337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 33347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3335ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 33365aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3337f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 333881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3339f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 334081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3341ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3342ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3343ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3344ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3345ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 33464da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 33474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 334873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 33495aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 33505aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 335181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3352f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 335381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3354ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3355ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3356ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3357127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 3358de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 3359b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3360b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3361b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3362eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3363e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3364e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 336543880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3366eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3367eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3368eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 33699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 33709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 33719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 33729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 33739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 337481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 337581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 3376f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 337781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 337800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 337900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 338000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 33814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 33824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 33839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 33849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 33859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 33869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 33879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 33889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 33899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 33909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 33919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 33929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 33939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 33949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 33959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 33969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 33979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 33989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 33999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 34009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 34019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 34029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 34039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 34049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 34059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 34069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 34079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 34089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 34099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 34109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 34119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 34129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 34139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 34149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 34159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 34169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 34179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 34189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 34199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 34209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 34219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 34229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 34239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 34249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 34259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 34269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 34279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 34289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 34299705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 34309705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 34319705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 34329705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 34339705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 34349705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 34359705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 34369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 34379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 34389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 34399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 34405aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 3441f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 344273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3443ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3444ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 344573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 3446f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 344773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 344873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 344973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 345073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 345173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 345273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 345373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 345473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3455ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 34561a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 34571a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 345894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 34596ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 34601129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 34616ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 3462e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 34636ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 34646ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 34656ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 34666ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 34676ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 34686ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 34696ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 34706ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 34716ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 3472ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 34736ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 34746ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 34756ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 34766ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 34776ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 34786ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 34796ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 34806ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 348194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 348294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 348394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 3484b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 3485b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 3486e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 34871a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 34881a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3489e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3490e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3491e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3492e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 34934529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 34944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 34954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 34964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 34974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 349873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 34994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3500b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 350151bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 35024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 35034529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 35044529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 35054529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 35064529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 35074529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 35084529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 35094529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 35104529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 35114529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 35124529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 35134529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 35144529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 35154529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 35164529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 351796b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 351896b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 351919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 352019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 352119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 3522ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 3523ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 352419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 352519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 352696b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1, null, null, null); 352719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 352819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 352919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 3530ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 3531ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 353219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 353319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 353419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 353519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 353619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 353719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 353819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 3539f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 354096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker int count = mDb.update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 35415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3542433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 35434529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3544433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3545285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 35462b7a632bba423357ae5641f94da6a2f71afc523bDmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(mDb, rawContactId); 3547285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 3548f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 3549f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 3550f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 3551f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 3552f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 3553f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(1, rawContactId); 3554f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(2, rawContactId); 3555f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.execute(); 3556f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 3557f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(mDb, rawContactId); 3558f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 355919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 356019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 3561ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.put(rawContactId, new Account(accountName, accountType)); 356219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 35635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 356533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 356633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3567321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3568f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 356920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 357020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 357120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 35725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 357320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 357420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 357520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 357620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 357720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3578b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 357920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 358020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 358170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 358270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 358320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 358420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 358520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 358670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 358720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 358870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 358920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 359070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 359120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 359270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 359320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 359420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3595653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 359620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3597653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3598653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 359914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 3600653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 3601653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 3602f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 360320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3604653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 3605653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 360620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 360720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3608653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 360920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 361020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3611f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 3612653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 3613653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 3614321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3615653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 361614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 3617a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3618f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana rowHandler.update(mDb, values, c, callerIsSyncAdapter); 36198e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 3620a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 3621a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 3622a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 36238e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 3624653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 3625321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3626321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 36278c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 36288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 36298c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 3630b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 36318c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 36328c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 36338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 36348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 36358c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 36368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 36378c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 36388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 36398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 36408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 36418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 36428c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 36438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 36448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 36458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 36468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 3647d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 36488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3649b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3650d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3651b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 3652d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3653b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 3654d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3655b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3656d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3657b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3658d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 3659d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3660d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 36618c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 3662d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 3663d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3664d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 36658c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 3666c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 36678c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3668c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 3669c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 36704da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 36714da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?", mSelectionArgs1); 36728c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 36738c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 36748c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 36758c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3676b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 36778c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3678b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 36798c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3680b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 36818c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3682b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 36838c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3684b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 36858c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 36868c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 36879b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori int rslt = mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 36886e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 36899b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 36909b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 36919b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 36929b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 36939b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 36949b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 3695f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3696d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3697127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 3698127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 36990c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 37000c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 370180c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 37020c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 37030c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 37040c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 37050c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 37060c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 37070c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 37080c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 3709b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3710127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 37110c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 37124da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 37134da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 37140c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 37154da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 37164da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 37170c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 37186bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 37196bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 37200c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 37210c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 37220c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 37230c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 3724127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 3725127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 37263389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3727dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 3728dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 3729dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 3730b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 37310c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 37320c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 3733b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId2 = mDbHelper.getContactId(rawContactId2); 37340c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 3735127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3736127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 3737127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 3738127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3739b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3740b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 374170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 3742b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 374370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (mDb == null) return; 374470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 3745627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 3746627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov boolean hasUnassignedContacts[] = new boolean[]{false}; 374770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 374870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 3749627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3750627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.RAW_CONTACTS, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE); 3751627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3752627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.GROUPS, Groups.ACCOUNT_NAME, Groups.ACCOUNT_TYPE); 3753627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3754627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.SETTINGS, Settings.ACCOUNT_NAME, Settings.ACCOUNT_TYPE); 375548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3756627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 3757627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // in the existingAccounts set will be extra accounts whose data must be deleted. 3758627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 3759627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 3760627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 376170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 376270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 376370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 37645f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 3765627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 3766627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3767627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 3768627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 3769627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 3770627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3771627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 3772627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 3773627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "SELECT " + RawContacts._ID + 3774627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 3775627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3776627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 3777627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3778627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 3779627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3780627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 3781627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3782627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 3783627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 3784627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 3785627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3786627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3787627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (hasUnassignedContacts[0]) { 3788627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3789627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Account primaryAccount = null; 3790627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 3791627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (isWritableAccount(account)) { 3792627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov primaryAccount = account; 3793627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov break; 3794627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3795627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3796627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3797627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (primaryAccount != null) { 3798627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {primaryAccount.name, primaryAccount.type}; 3799627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3800627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3801627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 3802627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + RawContacts.ACCOUNT_NAME + "=?," 3803627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=?" + 3804627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + 3805627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL", params); 3806627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3807627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // We don't currently support groups for unsynced accounts, so this is for 3808627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // the future 3809627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3810627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.GROUPS + 3811627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + Groups.ACCOUNT_NAME + "=?," 3812627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + Groups.ACCOUNT_TYPE + "=?" + 3813627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " IS NULL" + 3814627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " IS NULL", params); 3815627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 381670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3817627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3818b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 381970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 382070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 382170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 382270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 382370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3824619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3825619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3826627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 3827627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 3828627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov private void findValidAccounts(Set<Account> validAccounts, boolean[] hasUnassignedContacts, 3829627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String table, String accountNameColumn, String accountTypeColumn) { 3830627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Cursor c = mDb.rawQuery("SELECT DISTINCT " + accountNameColumn + "," + accountTypeColumn 3831627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + " FROM " + table, null); 3832627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 3833627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 3834627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (c.isNull(0) && c.isNull(1)) { 3835627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov hasUnassignedContacts[0] = true; 3836627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } else { 3837627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 3838627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3839627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3840627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 3841627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 3842627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3843627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3844627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3845627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov /** 3846622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 3847622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 384867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 384967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 385067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 385167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 385267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 385367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 385467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 385567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 385667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 385767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 385867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 385967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 3860dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 3861622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 3862dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 3863dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 3864622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3865622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3866dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 3867622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3868622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 38694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 38704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 38714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 3872bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3873bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3874bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 38750b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 3876b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 387735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3878d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 38791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3880c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3881c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3882619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3883619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3884a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 38854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 388635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3887b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 388835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 388935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3890d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3891763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3892619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3893619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3894619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3895d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 38964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3897763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 38984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 38994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 39006bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 39016bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 39026bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 39035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 39045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 39055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 39065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 39075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 3908fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3909fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 39105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 39125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 39132d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill // TODO: pull this out into a method and generalize to not require contactId 39145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 39155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3916763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 39174da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String[] args; 39184da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (selectionArgs == null) { 39194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[2]; 39204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } else { 39214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[selectionArgs.length + 2]; 39224da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 39234da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 39244da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args[0] = String.valueOf(contactId); 39254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args[1] = lookupKey; 39264da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 39274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 39285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 39295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 39305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 39315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 39345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3936763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 39374da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 39384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 39394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 39405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 39415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3943f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 3944f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 3945f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 3946763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 3947f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 39484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 39494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 39504da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 3951f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 3952f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 3953f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 3954ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3955916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 3956ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 3957916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 3958ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3959916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet(qb, uri, projection, filterParam); 3960ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3961ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3962ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3963ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3964ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 39654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3966ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3967d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 39684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 39694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3970e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 39715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 39724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 39734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 39744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3975763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3976ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 39775e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 39785e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 39795e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 39805e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar starredProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 39815e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar frequentProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 39825e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 39835e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 39844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 39854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 39864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3987d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 39885e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 39895e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 39904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3991d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3992d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3993d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3994763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 39954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 39964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3997d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 39985e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 39995e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 4000d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 4001d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 40024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 4003d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4004d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 4005d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 4006d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 40074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 40084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 4009d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 4010d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 4011d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4012d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 4013d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4014d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4015ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 4016763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4017b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 401871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 40194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 4020b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4021b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 4022b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4023b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 4024d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 40254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 402682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 40274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 40284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 40296bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 40306bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 403100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 4032ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 40333653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 403482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 40354da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 40364da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 40373653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 40383653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 40393653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 40403653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 40414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 404282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 404389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 40442815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 40452815f58f72f109790585931f601a63ddc02536a5Evan Millar } 40462815f58f72f109790585931f601a63ddc02536a5Evan Millar 404748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 404882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 40494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 405048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 40514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 405248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 405348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 405448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 4055ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 405682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 405789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 4058ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 40594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 40604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4061a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 40625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 40635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 40645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 40655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 40665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 40677318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 40685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 40695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 40705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 40715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 40725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 40735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 40745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 40755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 40765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 40775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 40785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 40795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 40805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 40815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 40825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 40835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 40845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4085a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 4086ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 40875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 4088a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4089a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4090a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 4091ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4092ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4093ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 40944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 409582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 409689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 40974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 40984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 40994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 410048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 410182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 41024da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 41034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 41044da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 410548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 410648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 410748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 41085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 410982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 411089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 41114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 41124da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 41134da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Email.DATA + "=?"); 41144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 4115ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4116ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4117ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 41185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 411982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 412007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 412107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 412207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 412307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 412407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 412507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 412607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 41275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 412807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 412907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 413007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 413107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 413207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 413307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 413407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 413507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 413607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 413707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 413807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.DATA1 + " LIKE "); 413907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 414020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 414120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 414220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 414307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 414407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov /* 414507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * Using a UNION instead of an "OR" to make SQLite use the right 414607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * indexes. We need it to use the (mimetype,data1) index for the 414707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * email lookup (see above), but not for the name lookup. 414807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * SQLite is not smart enough to use the index on one side of an OR 414907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * but not on the other. Using two separate nested queries 415007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * and a UNION between them does the job. 415107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov */ 415207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 415307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " UNION SELECT " + Data._ID + 415407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 415507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 415607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN "); 41577318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 415820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 41595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4161a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 41625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 4164a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4165a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4166a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 41675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 41685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 4170ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 417182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 417289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 417389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 4174ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4175ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4176ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 417748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 417882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 41794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 418048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 418148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 41824da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 418348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 418448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 418548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 41865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 4187763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 41884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 41894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 41904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 41915ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 41925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 4193763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 41944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 41954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 41964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 41974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 41984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 41995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 42005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 420182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 42024da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 42034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 4204e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4205e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4206e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 4207e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 420882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 4209e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4210e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4211e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 42124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 421382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 42144da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 42154da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 4216a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 4217a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 4218a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 4219a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 42204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4221a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 4222a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 4223a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 4224e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 4225a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4226a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4227e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 4228b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 4229e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 4230e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 4231e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 4232e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 4233e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 4234a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 4235a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4236a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4237ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 4238b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4239ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 424089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4241ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4242ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4243ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4244ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 4245b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4246ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 42474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 42484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 4249ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4250ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4251ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4252ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 4253b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 4254ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 425589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 425689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 4257ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4258ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4259ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4260b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 42610c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 4262b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 4263b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 4264b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4265b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 426631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 4267d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 42682d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 42692d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 42702d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 42712d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 427231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 4273d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 4274d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 427531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 427631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 427731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 427831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4279763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 42807581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 42817581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 42822d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 428331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 428431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4285eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 4286eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 4287eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 428889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4289e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4290e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 4291e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 4292b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 4293e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 429482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4295b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 4296e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4297e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 429882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4299b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 4300e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4301e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4302e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4303eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 4304eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 4305eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 430682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 43070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 43085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 43095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 43105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 431182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 43120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 43134da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 43144da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 43155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 43165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 43175ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 4318c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 4319a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 4320c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4321c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4322c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 43232d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 43242d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill return mGlobalSearchSupport.handleSearchShortcutRefresh(db, lookupKey, projection); 4325c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4326c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 43271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 4328b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 43291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 43301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 43311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 43321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 4333b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 43341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 43351b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 43361b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 43371b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 43381b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 4339b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 43401b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 43411b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 43421b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 43431b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 43441b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 4345b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 43461b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 434771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 43481b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 43491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 43501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 435146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 435246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 435346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 435446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 435546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 435646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 435746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 435846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 43594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 43604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 436146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 436246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 436346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 43644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 4365f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 4366c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 43674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 43684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 4369ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 4370ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 4371ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 4372ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov cursor = bundleLetterCountExtras(cursor, db, qb, selection, selectionArgs, sortOrder); 4373ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4374ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 43755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 43785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 43795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 4380038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 4381038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 4382038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 4383038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 43845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 43855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 43864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 43874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 43884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 43894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 43904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 43914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 4392bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 4393bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 4394bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 4395bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 4396ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4397bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 4398bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 4399ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 4400ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4401bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 4402bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 4403bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 4404bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4405ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // TODO change to LOCALIZED2 once that becomes available 4406bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String ORDER_BY = LETTER + " COLLATE LOCALIZED"; 4407ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4408ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4409ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 4410ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 4411ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 4412ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 4413ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 4414ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder) { 4415ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 4416ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4417ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 4418ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 4419ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 4420ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 4421ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 4422ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 4423ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 4424ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 4425ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 4426ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 4427ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 4428ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4429ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 4430ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 4431ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4432ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4433bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 4434ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 4435bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 4436bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "SUBSTR(" + sortKey + ",1,1) AS " + AddressBookIndexQuery.LETTER); 4437bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4438bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 4439bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 4440bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 4441bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 4442bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 4443bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 4444bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 4445ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 4446bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "GET_PHONEBOOK_INDEX(SUBSTR(" + sortKey + ",1,1),'" + locale + "')" 4447bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 4448ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 4449ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov "COUNT(" + Contacts._ID + ") AS " + AddressBookIndexQuery.COUNT); 4450ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 4451ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4452f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 4453ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 4454ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 4455ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4456ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 4457f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 4458ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 4459ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 4460bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 4461bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 4462bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4463bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 4464bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 4465bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 4466ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 4467f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 4468bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 4469bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 4470bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 4471bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 4472bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 4473bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 4474bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 4475bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 4476bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4477bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4478bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4479bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 4480bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 4481bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 4482bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 4483bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4484bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 4485bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 4486bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 4487ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4488ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4489ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov final Bundle bundle = new Bundle(); 4490ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 4491f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 4492ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return new CursorWrapper(cursor) { 4493ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4494ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov @Override 4495ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov public Bundle getExtras() { 4496ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return bundle; 4497ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4498ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 4499ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 4500f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 4501ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4502ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4503ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 45042d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 45052d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill * Returns the contact Id for the contact identified by the lookupKey. Robust against changes 45062d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill * in the lookup key: if the key has changed, will look up the contact by the name encoded in 45072d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill * the lookup key. 45082d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 45092d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 45105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 45115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 45125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 45145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 45155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 45165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 45195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 45225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 45235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 45255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 45265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 45275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 45285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 45295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 45305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 45325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 45335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 45345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 45355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 45385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 45395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 45405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 45415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 45425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 45435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 45445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 45485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 45495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 45525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 45535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 45545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 45555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 45565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 45575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 45585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 45595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 45625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 45635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 45655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 45665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 45675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 45685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 45695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 45705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 45715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 45725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 45735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 45745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 45755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 45765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 45775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 45785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 45795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 45835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 45845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 45875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 45885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 45905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 45915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 45935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 45945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 45955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 45965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 45975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 45985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 45995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 46005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 46015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 46025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 46035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 46055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 46065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 46075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 46085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 46095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 46105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 46115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 46125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 46155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 46165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 46175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 46195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 46205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 46215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 46225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 46235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 46245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 46255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 46265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 46275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 46305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 46315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 46325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 46335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 46345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 46355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 46365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 46375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 46385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 46395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 46405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 46415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 46425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 46435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 46445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 46455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 46465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 46475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 46485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 46525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 46535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 46555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 46565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4658ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 4659ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(db, rawContactId); 4660ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 4661ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 46625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 46635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 46645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 46655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 46665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 46675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 46685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 46695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 46705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 46715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 46725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 46735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 46745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 46755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 46765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 46775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 46785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 46795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 46805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 46815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 46825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 46835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 46845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 46865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 46875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 46915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 46925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 46935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 46945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4697763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 4698763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 469982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4700916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 4701916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 4702916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 4703916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4704916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4705916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 4706916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 4707916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 4708916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 4709916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 4710916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String[] projection, String filter) { 4711916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4712916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4713916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 4714916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4715916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(" JOIN (SELECT " + 4716916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov RawContacts.CONTACT_ID + " AS snippet_contact_id"); 4717916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4718916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA_ID)) { 4719916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", " + DataColumns.CONCRETE_ID + " AS " 4720916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov + SearchSnippetColumns.SNIPPET_DATA_ID); 4721916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4722916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 47239c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA1)) { 47249c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA1 + " AS " + SearchSnippetColumns.SNIPPET_DATA1); 4725916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4726916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 47279c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA2)) { 47289c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA2 + " AS " + SearchSnippetColumns.SNIPPET_DATA2); 4729916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4730916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 47319c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA3)) { 47329c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA3 + " AS " + SearchSnippetColumns.SNIPPET_DATA3); 47339c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 47349c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov 47359c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA4)) { 47369c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA4 + " AS " + SearchSnippetColumns.SNIPPET_DATA4); 4737916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4738916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4739916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_MIMETYPE)) { 4740916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", (" + 4741916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov "SELECT " + MimetypesColumns.MIMETYPE + 4742916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " FROM " + Tables.MIMETYPES + 4743916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + MimetypesColumns._ID + "=" + DataColumns.MIMETYPE_ID + 4744916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov ") AS " + SearchSnippetColumns.SNIPPET_MIMETYPE); 4745916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4746916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4747916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS + 4748916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + DataColumns.CONCRETE_ID + 4749916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN ("); 4750916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4751916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // Construct a query that gives us exactly one data _id per matching contact. 4752916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // MIN stands in for ANY in this context. 4753916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append( 4754916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov "SELECT MIN(" + Tables.NAME_LOOKUP + "." + NameLookupColumns.DATA_ID + ")" + 4755916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 4756916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 4757916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " ON (" + RawContactsColumns.CONCRETE_ID 4758916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov + "=" + Tables.NAME_LOOKUP + "." + NameLookupColumns.RAW_CONTACT_ID + ")" + 4759916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + " GLOB '"); 4760916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(NameNormalizer.normalize(filter)); 4761916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 4762916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + ")" + 4763916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " GROUP BY " + RawContactsColumns.CONCRETE_CONTACT_ID); 4764916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4765916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(")) ON (" + Contacts._ID + "=snippet_contact_id)"); 4766916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4767916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 4768916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 4769916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4770916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4771916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void appendContactsTables(StringBuilder sb, Uri uri, String[] projection) { 4772763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4773f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4774763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4775763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4776d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4777763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4778763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 4779b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 478082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 478182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 478282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 478382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4784b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 478582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 478682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 478782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 478882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 478982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 47903296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 47913296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 4792a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 47933296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 479482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 479582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4796ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 4797763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 4798763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 4799763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4800f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4801763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4802763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4803d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4804763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4805763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 4806763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 4807763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 4808763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 4809763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4810763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 481146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 481246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana // Note: currently, "export only" equals to "restricted", but may not in the future. 481346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana boolean excludeRestrictedData = readBooleanQueryParameter(uri, 481446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.FOR_EXPORT_ONLY, false); 481546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 4816f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 481746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 481846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana if (requestingPackage != null) { 481946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana excludeRestrictedData = excludeRestrictedData 482046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 482146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 482246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 482346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setProjectionMap(sRawContactsEntityProjectionMap); 482446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 482546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 482646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 482782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 482882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 482982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4830d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa // Note: currently, "export only" equals to "restricted", but may not in the future. 4831763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = readBooleanQueryParameter(uri, 4832d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa Data.FOR_EXPORT_ONLY, false); 4833763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4834f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4835763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4836763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4837763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar excludeRestrictedData = excludeRestrictedData 4838d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4839763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4840763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4841763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getDataView(excludeRestrictedData)); 484282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 484382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 48443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated presence when requested 4845b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 484682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 48473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 484882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 484982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 485082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 48513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated status updates when requested 4852b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 485382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 485482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 485582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 485682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 485782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 48583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 48593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 486082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 48613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 4862ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 48633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 48643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual presence when requested 48653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 48663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 48673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdates.DATA_ID + "=" 48683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 48693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 48703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 48713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual status updates when requested 48723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, 48733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS, 48743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_RES_PACKAGE, 48753296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_ICON, 48763296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_LABEL, 48773296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_TIMESTAMP)) { 48783296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 48793296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 48803296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 48813296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 48823296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 488382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 488482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 488582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 4886ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 4887ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 48880a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 48890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 48900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4891b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 48920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 48930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4894b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 48950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 48960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 48970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 48980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 48990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4900b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 49010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 49020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 49030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 49040a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 49050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 49060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 49070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 49080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 49090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 49100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setTables(sb.toString()); 49110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 49120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 49130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 49144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 4915f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 4916f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 4917e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4918e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 4919e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 4920e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 4921fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4922fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 4923e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4924e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4925e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 4926e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 4927e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 4928e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 49294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 49304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 49314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 49324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 49334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 49344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 49354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 49364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 49374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4938e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 4939f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 4940f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 4941e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4942e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 4943e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 4944e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 4945fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4946fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 4947e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4948e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4949e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 4950e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 4951e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 4952e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 4953e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 4954e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4955e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 4956e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 4957e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 4958e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 4959e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 4960e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 4961e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4962e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 4963e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 4964e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 4965e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4966e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4967e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 49687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 4969c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 4970c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 4971c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 4972c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 4973c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 4974f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 4975f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String limitParam = getQueryParameter(uri, "limit"); 4976c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 4977c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4978c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4979c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 4980c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 4981c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 4982c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 4983c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4984c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4985c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4986c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 4987c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 4988c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4989c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4990c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4991c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4992c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 49935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 49945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 49955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 49965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 49975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 49985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 49995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 50005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 50015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 50025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 50035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 50045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 50055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 50065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 50075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 50085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 50095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 50105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 50115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 50125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 50135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 50145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 50155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 50165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 50175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 50185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 50195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 50205e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 50215e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 50225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 502300ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 5024d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 502570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 502670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 5027fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0"; 502870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 502970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 503070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 503170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 5032d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 503370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 503467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 50355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 50365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 5037619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5038619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5039619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 5040b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 5041b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 5042b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 5043b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 5044d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 5045b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 5046fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("Mode " + mode 5047fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov + " not supported.", uri)); 5048b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5049b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5050b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 5051b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 5052b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 50534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=?"; 5054b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 50554da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, 50564da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 5057d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5058d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5059f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 5060d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 5061d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 506214b8a1243ab5c043b35e47527ca1c962064f3771Daisuke Miyakawa final String selection = Contacts._ID + "=" + contactId; 5063d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5064d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 5065d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 5066d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 5067d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 5068d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey outputRawContactsAsVCard(localStream, selection, null); 5069d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 5070d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5071b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5072b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 5073fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("File does not exist", 5074fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov uri)); 5075b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5076b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5077b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5078d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 5079d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5080d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5081d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 5082d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 5083d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5084d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 5085d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 5086d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 5087d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 5088d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5089d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 5090d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 5091d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5092d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 5093d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 5094d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 5095b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5096d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 5097d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 5098d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 5099d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5100d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 5101d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5102d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5103d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5104d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 5105d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 5106d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 5107d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5108d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 5109d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 5110d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 51117a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 51127a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa new VCardComposer(context, VCardConfig.VCARD_TYPE_DEFAULT, false); 5113d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 5114d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5115f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 51167a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa if (!composer.init(selection, selectionArgs)) { 51177a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 5118d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 51197a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa } 5120d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5121d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 5122d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 5123d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 5124d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5125d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5126d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 5127d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5128b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 51294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 51304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 5131a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 51324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 5133b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 5134be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 51352d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 5136b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 5137b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 5138b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 5139f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 5140f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 5141b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 5142be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 5143b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 5144b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 5145508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 5146b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 514748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 514848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 514948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 515048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 51519005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 51529005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 515348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 515448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 515548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 515648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 515748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 515848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 515948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 516048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 5161b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 5162b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 5163b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 5164b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 5165b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 5166b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 5167b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 5168b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 5169c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 5170c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 5171c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 5172c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 5173d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov 517461efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 517561efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 51764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 51774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 51787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 51795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void setDisplayName(long rawContactId, int displayNameSource, 51805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary, String displayNameAlternative, String phoneticName, 51815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int phoneticNameStyle, String sortKeyPrimary, String sortKeyAlternative) { 51825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(1, displayNameSource); 51835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 2, displayNamePrimary); 51845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 3, displayNameAlternative); 51855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 4, phoneticName); 51865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(5, phoneticNameStyle); 51875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 6, sortKeyPrimary); 51885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 7, sortKeyAlternative); 51895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(8, rawContactId); 519025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 51913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 51923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 519373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 519473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 519573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 519673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 5197a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.add(rawContactId); 519873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 519973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 5200c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 5201c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 5202c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 5203c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 5204c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 5205c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 5206653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 5207c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 5208653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 5209653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 5210c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 5211c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 5212c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 5213c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 5214c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 5215c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 5216c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 5217c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 5218c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 5219653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 5220c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 5221653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 5222653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 5223c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 5224c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 5225ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 5226f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 5227f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 5228f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 5229f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5230f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5231b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String address = mDbHelper.extractHandleFromEmailAddress(email); 5232b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (address == null) { 5233f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 5234f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5235f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5236f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 5237f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 5238f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5239f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5240f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5241f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 5242f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5243f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 5244f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 5245f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 5246f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5247f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5248f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 5249f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 5250f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5251f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5252a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 5253a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 5254a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 5255a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 5256a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 5257a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5258a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 5259a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 5260a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 5261a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5262a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5263f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5264d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name, 5265d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov int fullNameStyle) { 5266d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle); 5267f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5268f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5269f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 5270f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5271f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 5272f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 5273f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5274f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5275f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5276f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 5277f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 5278f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 5279f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5280f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5281f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5282f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 5283d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 5284f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5285f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5286f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5287f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5288f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 5289f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5290f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 52915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(1, rawContactId); 52925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(2, dataId); 52935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(3, lookupType); 52945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mNameLookupInsert, 4, name); 5295f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 5296f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5297f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5298f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5299f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 5300f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5301f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 53025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupDelete.bindLong(1, dataId); 5303f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 5304f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5305f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 53062d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 5307d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5308d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 5309d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 5310d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 5311d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 5312d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 5313d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 5314e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 5315916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 5316916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 5317e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 5318e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 53195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 5320c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 53217318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam); 5322c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 5323c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5324c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 53257318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam) { 53267318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), true); 53275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 53295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 53307318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov boolean allowEmailMatch) { 5331d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5332dc947a9d03279eab0fb7c3b9d8ffbb492c1e2062Dmitri Plotnikov "SELECT " + NameLookupColumns.RAW_CONTACT_ID + 5333d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5334d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 5335d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 53365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 5337a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 5338a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 5339a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 53404cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao + NameLookupType.NAME_SHORTHAND + "," 534120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov + NameLookupType.ORGANIZATION); 534220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 534320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 534420938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 53457318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov sb.append("))"); 5346ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5347ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 53484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 53494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 53504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 53514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 5352b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 5353b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 5354b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 5355b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 5356b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 53574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 53584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 5359b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 5360b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5361b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5362caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 53635e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 53645e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 53655e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 53665e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 53675e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 53685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 53695e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 53705e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 53715e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 53725e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 53735e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5374caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 5375caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 5376caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 5377df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 5378df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 5379caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 5380caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 5381caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5382caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 53836f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 5384caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 53856f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 5386caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5387f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5388627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov protected boolean isWritableAccount(Account account) { 5389627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 5390627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 5391627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 5392627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 5393627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov account.type.equals(sync.accountType)) { 5394627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov return sync.supportsUploading(); 5395627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5396627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5397627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 5398627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 5399627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5400627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov return false; 5401627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5402b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 5403f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 5404f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 5405f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5406f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 5407f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5408f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5409f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5410f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5411f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5412f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 5413f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5414f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5415f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5416f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5417f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 5418f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5419f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 5420f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 5421f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5422f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5423f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 5424f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 5425f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 5426f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 5427f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 5428f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5429f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5430f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 5431f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 5432f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 5433f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 5434f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5435f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5436f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5437f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5438f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5439f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 5440f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 5441f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5442f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 5443f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 5444f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 5445f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 5446f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5447f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5448f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5449f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5450f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 5451f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5452f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 5453f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5454f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5455f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5456f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 5457f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 5458f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 5459f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5460f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5461f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5462f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 5463f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 5464f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 5465f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 5466f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 5467f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5468f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5469f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 5470f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 54715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 54725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindString(SQLiteStatement stmt, int index, String value) { 54735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 54745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 54755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 54765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindString(index, value); 54775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 54785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 54795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 54805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindLong(SQLiteStatement stmt, int index, Number value) { 54815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 54825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 54835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 54845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindLong(index, value.longValue()); 54855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 54865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 54874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 5488