ContactsProvider2.java revision 9b1bd62417ef1764829398a61c3d5df93a924106
14f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/* 24f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Copyright (C) 2009 The Android Open Source Project 34f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 44f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 54f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * you may not use this file except in compliance with the License. 64f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * You may obtain a copy of the License at 74f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 84f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 94f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Unless required by applicable law or agreed to in writing, software 114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * See the License for the specific language governing permissions and 144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * limitations under the License 154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts; 1828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar 193de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.internal.content.SyncStateContentProviderHelper; 203de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 21b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 22b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 23b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 24b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkeyimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 26b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 27b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DisplayNameSources; 28b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 29b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 30b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 31b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 32b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NicknameLookupColumns; 33b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 34b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 35b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 36b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 37b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 38b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 39b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 40a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Lists; 41a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Maps; 42a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Sets; 433de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 44b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 45caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 465b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 47c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 48568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 49568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 506ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 5135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 54627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.IContentService; 55568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 563d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 57627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 5867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 593de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.content.SharedPreferences.Editor; 60b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 611129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikovimport android.database.CharArrayBuffer; 624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 63ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 64a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 65b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 66b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 69c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 716ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 72d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 73b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 740e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 75d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 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; 833de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 843de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 853de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 863de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 873de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 883de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 8982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 91ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 92ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 96de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 97b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 984097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 9967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 100a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 101a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 102f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Token; 103f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer; 104c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 106d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 107b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 108d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 109d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 110f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport java.lang.ref.SoftReference; 1117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 112315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikovimport java.util.BitSet; 1135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 114b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1150e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 117622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 118b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1190e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 120ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1265b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 127caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 128bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 129bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 130bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 132619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 133619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 134619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1453d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1460e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1470e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 148a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1505e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final String TIMES_CONTACED_SORT_COLUMN = "times_contacted_sort"; 1515e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 152d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 1535e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar + TIMES_CONTACED_SORT_COLUMN + " DESC, " 1549b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 155d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 156d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 157d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 158d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1599b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori private static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 1609b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 1619b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1629b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 1639b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 1649b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori private static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 1659b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 1669b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1679b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 1689b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 169d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 170d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 179f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 1804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 18446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 1854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1866bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1876bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 188ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 18948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 19048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 19148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 19248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 19348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 19448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 19548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 19648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 197a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1986bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1996bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 200b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 201b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 202b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 20382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 20482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 2051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 20631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 20731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 208eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 209eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 210ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 211ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 212ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 213ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 21435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 215b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 21635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 217c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 218c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 219c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 22546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 22646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 227d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 228f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 229f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 230f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 23167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 23267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2336cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 235f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 236ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 237ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 238d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 23967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 240d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 241ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 24314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 24467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 24688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 251f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 25288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 25388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 25488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 25588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 25688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 25788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 25888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 259f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 2603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 266f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 2673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 270321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 27120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 27220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 273321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 274321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 27520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 27620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 277f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 27819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 27919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 28019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 28119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 282ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 283ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 284ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 28519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 28619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 28719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 288ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 289ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 29019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 29119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 292c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 293df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 294caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 29571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 29671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 29771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 29871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 29971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 30071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 30171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 30271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 30371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 30471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 30571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 30671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 30771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 30871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 309a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 310a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 311a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 312a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 313a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 314a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 315a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 316a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 317a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 318a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 319a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 320a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 321038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 322038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 323e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 3255e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 3265e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentStarredProjectionMap; 3275e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentFrequentProjectionMap; 328f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 329f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final HashMap<String, String> sContactsVCardProjectionMap; 330ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 331d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 33246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** Contains the columns from the raw contacts entity view*/ 33346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final HashMap<String, String> sRawContactsEntityProjectionMap; 3344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3389261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 339e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 340ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 341ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 342ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 343ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 344373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 345b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 346eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 347eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 34882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 34982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 3501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 3549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 3559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 3569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 3579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 3589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 359c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 360c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 362c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 363ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton /** Precompiled sql statement for incrementing times contacted for a contact */ 364ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton private SQLiteStatement mContactsLastTimeContactedUpdate; 3653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 36625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 36782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 368a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 369f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 370f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 371a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 372a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 373a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 3740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 375a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 376a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 377f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 378f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 3791129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdStructuredName; 3801129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdOrganization; 3811129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdNickname; 3821129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdPhone; 383f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 3841129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 3851129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 3861129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs3 = new String[3]; 387f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 388f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 3904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 391a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 392d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 393d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 394d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 3953653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 3963653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 3972d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 3982d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 3993653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 4005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 4015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 4025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 403f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 4045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 405ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 406ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 4075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 4083653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 41246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 41346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 41446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 415b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 418ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 41948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4205e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 421ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 42348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 427ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 42848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 430ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 431ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 432ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 433ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 43435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 435b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 436b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 43735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 438a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 439b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 440b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 441b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 442b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 444eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 445eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 44682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 44782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 4481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 449c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 450c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 451c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 452c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 453c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 454c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 455c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4571b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 4601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 4611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 4621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 4631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 46419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 46519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 46619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 467038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 468038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 469e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 4714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 4724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 4734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 479f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 4804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 482f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 4833296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 4843296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 4853296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 4863296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 4873296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 4883296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 4893296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 4903296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 4913296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 4923296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 4933296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 4943296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 4953296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 4963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 4975e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 4985e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 4995e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Long.MAX_VALUE + " AS " + TIMES_CONTACED_SORT_COLUMN); 5005e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5015e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5025e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5035e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Contacts.TIMES_CONTACTED + " AS " + TIMES_CONTACED_SORT_COLUMN); 5045e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 505f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap = Maps.newHashMap(); 506f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 507d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 508f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "0 AS " + OpenableColumns.SIZE); 5094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 5114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 5124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 5184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 5194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 5204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 5214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 5224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 5234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 5244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 5254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 5264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 5274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 5284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 5294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 5302815f58f72f109790585931f601a63ddc02536a5Evan Millar 5314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 5324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 5334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 5344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 5404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 5414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 5424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 5434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 5444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 5454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 5464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 5474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 5484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 5494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 5504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 5514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 5524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 5534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 5544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 55882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 5594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 56456d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 572a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 5734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 574a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 57546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana HashMap<String, String> columns; 57646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns = new HashMap<String, String>(); 57746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts._ID, RawContacts._ID); 57846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 57946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 58046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 58146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 58246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.VERSION, RawContacts.VERSION); 58346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 58446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DELETED, RawContacts.DELETED); 585bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey columns.put(RawContacts.IS_RESTRICTED, RawContacts.IS_RESTRICTED); 58646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 58746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 58846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 58946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 59046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 59146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.MIMETYPE, Data.MIMETYPE); 59246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA1, Data.DATA1); 59346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA2, Data.DATA2); 59446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA3, Data.DATA3); 59546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA4, Data.DATA4); 59646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA5, Data.DATA5); 59746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA6, Data.DATA6); 59846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA7, Data.DATA7); 59946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA8, Data.DATA8); 60046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA9, Data.DATA9); 60146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA10, Data.DATA10); 60246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA11, Data.DATA11); 60346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA12, Data.DATA12); 60446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA13, Data.DATA13); 60546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA14, Data.DATA14); 60646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA15, Data.DATA15); 60746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC1, Data.SYNC1); 60846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC2, Data.SYNC2); 60946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC3, Data.SYNC3); 61046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC4, Data.SYNC4); 61146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 61246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.STARRED, Data.STARRED); 61346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 61446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 61546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 61646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 61746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana sRawContactsEntityProjectionMap = columns; 61846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 6193296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 6203296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 6213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 6223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 6233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 6243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 6253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 6293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 6313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 6323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 6343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.PRESENCE, 6353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 6363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS, 6373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 6383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 6393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 6413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_LABEL, 6433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_ICON, 6453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 6463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 6485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 6495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 6505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 6515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 6525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 6535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 6545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 6555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 6565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 6575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 6585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 6595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 6605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 6615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 6625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 6635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 6645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 6655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 6665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 6675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 6685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 6695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 6705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 6715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 6725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 6735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 6745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 6755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 6768f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 6775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 6785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 6795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 6805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 6815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 6825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 6835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 684a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 6855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 6865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 6875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 6883296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 6893296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 6903296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 6913296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 6923296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 6933296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 6943296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6953296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6973296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 6983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 7003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 7013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 7033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 7043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 7053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS, 7063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 7073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 7083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 7103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 7123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 7143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 7153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 716e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 717e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 718fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts._ID 719fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup._ID); 72056d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 721fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LOOKUP_KEY 722fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.LOOKUP_KEY); 723e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 724fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.DISPLAY_NAME 725fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.DISPLAY_NAME); 726e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 727fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LAST_TIME_CONTACTED 728e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 729e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 730fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.TIMES_CONTACTED 731fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.TIMES_CONTACTED); 732e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 733fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.STARRED 734fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.STARRED); 735e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 736fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.IN_VISIBLE_GROUP 737fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 738e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 739fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.PHOTO_ID 740fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.PHOTO_ID); 741e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 742fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.CUSTOM_RINGTONE 743fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.CUSTOM_RINGTONE); 744e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 745fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.HAS_PHONE_NUMBER 746fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 747e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 748fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.SEND_TO_VOICEMAIL 749e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 750e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 751e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 752e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 753e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 754e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 755e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 7569261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 757ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 758ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 75989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 760035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 761035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 7629261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 7639261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 7649261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 76589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 766ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 76767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 768ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 7693cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 77094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 7713cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 77238446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 77389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 77489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 77589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 77689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 777ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 778ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 7796cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 780ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 781ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 782d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 783d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 784ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 785ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 786ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 787d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 788d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 789ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 790f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 791ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 792ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 793b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 794b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 795b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 796b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 7970c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 7980c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 799b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 800b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 801eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 802eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 803eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 804eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 805eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 806eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 807341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 808341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 809341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 810fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 811341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 812341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 813341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 81468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 81568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 81668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 81768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 81868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 819e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 82068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 82168936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 82268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 823eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 824eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 825373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 8264dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 8270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 8280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 82982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 83082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 83182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 83270c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 83370c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 83482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 83582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 83682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 83782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 8380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 8390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 8400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 8410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 8420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 84382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 84419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 8451b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 8461b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 8471b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 8481b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 8491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 8501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 8511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 8521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 8531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 8541b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 8551b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 8564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 8574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 8583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 8593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey map.put(toField, fromField + " AS " + toField); 8603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 8613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 8623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 8643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 8663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 868653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 8693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8701129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov @SuppressWarnings("all") 8713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 8723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 873a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 874a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 875a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 876a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 877a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 878a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 879a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 880a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 8813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 883653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 884653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 885b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 886653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 887653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 888653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 889653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 8903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 8923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 894e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 895e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 896e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 897e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 898653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 899e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 900e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 901e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 9023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 9063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 9073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 908653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 909f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 91014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 91114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 912653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 913653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 914653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 915653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 916653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 917653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 918653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 919653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 920653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 921653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 922653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 923653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 924653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 925653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 926653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 927653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 928653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 9294da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 9304da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " =?", mSelectionArgs1); 931653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 932653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 933f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 934653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 935653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 9363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 93914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 94014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 94114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 9424da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 9434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=?", mSelectionArgs1); 9444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 9454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=?", mSelectionArgs1); 9463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 9475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 9483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 9503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 9534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov long mimeTypeId = getMimeTypeId(); 954e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 955e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 9564da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 9574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = db.query(DataDeleteQuery.TABLE, 9584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov DataDeleteQuery.CONCRETE_COLUMNS, 9594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Data.RAW_CONTACT_ID + "=?" + 9604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov " AND " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId, 9614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 9623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 963e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 96414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 965f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 966e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 967e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 968e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 969e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 9703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 9723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 9733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (primaryId != -1) { 9754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov setIsPrimary(rawContactId, primaryId, mimeTypeId); 9764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 977e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 978e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 979e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 980e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 981e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 982e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 983e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 984e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 9853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 98725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 988285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 989d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(db, rawContactId); 990fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(db, rawContactId); 991285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 9923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 993a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 994a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 995a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return true; 996a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 997622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 998622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 999622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 1000622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * as baseline, but augmented with any updates. 1001622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1002622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 1003622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 1004622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 10054da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10064da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=?", 10074da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 1008622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 1009622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 1010622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 1011622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 1012622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.put(key, cursor.getString(i)); 1013622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1014622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1015622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 1016622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 1017622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1018622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 1019622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 1020622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 10243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 10263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1031622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 10323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1033622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 10343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1035622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 10363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 10395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1040622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 104114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 104214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 104314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1044f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1045f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 104625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 104714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 104814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 104914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 105014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 105114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1052f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1053622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1054622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1055cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1056622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1057622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 105814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1059f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 106014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1061f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 1062f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1063f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1064f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 106514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 106625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 106714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 106814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 106914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 107014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 107114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 107214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 107314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 107414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 107514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1076f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 107725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 107814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 10793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1082622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 10833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1084622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1085622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1086622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1087622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 10883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1089622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1090622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1091622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1092622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1093622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1094622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1095622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 109667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1097622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 109867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 109967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1100622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1101622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 11028c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1103622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1104622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 110567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 110667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 110767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 110867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 110967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 111067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 11118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1112622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 1113622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(name); 1114622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 1115622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1116622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1117622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1118622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1119622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1120622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1121622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1122622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1123622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1124622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1125622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1126622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1127622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1128622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1129622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1130622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1131622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1132622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1133622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1134622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1135f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1136622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1137622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1138622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1139f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1140622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1141622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1142622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1143622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1144622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1145622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1146622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1147622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1148622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1149622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1150622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1151622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1152622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1153622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1154622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1155622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1156622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1157622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 115867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 115967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 116067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 116167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1162622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1163622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1164622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1165622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1166622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1167622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 116867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 116967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 117067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1171622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1172622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1173622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 11743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 11793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 11813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 11823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 11843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 11853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 11863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 11873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1191622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1192622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1193622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1195622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1196622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1197f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1198622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1199622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1200622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1201f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1202622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1204622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1205622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1206622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1207622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1208622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1209622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1210622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1211622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 12123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1213622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1214622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1215622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1216622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1217622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 12223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 12243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 12253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12285ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1229a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1230a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1231a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1232a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1233a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 123425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1235a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1236a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 12373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 124014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1241f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1242a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1243a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1244a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 124514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 124614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1247f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 124814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 124925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1250a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 1251a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 125214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 125314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 125414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 125514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1256a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 125714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 125814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 125914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 126025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1261a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 126214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 126314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 126414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 126514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 12663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 12673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 12683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 12693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 12703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 12713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 12723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1274a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1275a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1276a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1277a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1278a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 12793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1281e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1282e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1283e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1284e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1285e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1286e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1287e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 12885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 128914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 129014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 129214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1294f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 129514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 129614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 129714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 129914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1300f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 130114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 130214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 130314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 130414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1305f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 130614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1307f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1308f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 130925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 131014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 131114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 131214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 131314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 131414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 131514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 131614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 131714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 131814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1319f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 132025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 132114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1322e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1323e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1324e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1325e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1326e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1327e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1328e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1329e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1330e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1331e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1332e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1333e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1334e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1335e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 133614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 133714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 133814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 133914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 134014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 134114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 134214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 134314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 134414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 134514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 134614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 134714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 134825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1349f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 135014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 135114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 135214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 135314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 135414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1355f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 135614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 135714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 135814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 135914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1360f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 136114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1362f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1363f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 136425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 136514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 136614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 136714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 136814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 136914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 137014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 137114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 137214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 137314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1374f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 137525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 137614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 137714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 137814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 137914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 13803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 13813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 13833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 13843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 13880b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 13890b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 13900b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 13910b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1392653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 13930b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1394653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 13950b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1396285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 139725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 13980b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 13990b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 14000b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1401653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1402653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1403653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1404653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1405653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1406f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 140714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 140814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 14090b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 14100b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 14110b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1412653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1413f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1414653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14150b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1416285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 141725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 14180b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 1419f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 14200b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 142114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 142214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 142314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 142414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 142514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 142614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 142714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 142814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 142914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 143014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1431285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 143225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 143314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1434653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1435653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1436653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1437e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1438e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1439e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1440e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1441653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1442653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1443653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1444e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1445653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1446653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1447e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1448653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 14495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1450653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1451e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 145236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.MIN_MATCH, 145336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov PhoneNumberUtils.toCallerIDMinMatch(number)); 145436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov 1455653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1456653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 14574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 14584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=?", mSelectionArgs1); 1459e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 14603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 14633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 14643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 14653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 14663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 14673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 14683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 14693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 14703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 14713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 14723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 14733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 14743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1478653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1479653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1480653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1481653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1482653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1483653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1484653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1485653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1486653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 14870be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 14880be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 14890be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1490653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1491653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1492653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1493653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1494f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 149514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1496653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1497f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 14980be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 14990be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 15000be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 15010be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 15020be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 15030be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 15040be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 15050be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15060be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 15070be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 15080be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 15090be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1510b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 15110be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1512b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 15130be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1514653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1515653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1516653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1517653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1518653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1519653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1520653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1521653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1522653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1523653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1524653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1525653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1526653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1527653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1528653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1529653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1530653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1531653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1532653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1533653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1534653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1535653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1536653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1537653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1538ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId, 1539ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.get(rawContactId)); 1540653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1541653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1542653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1543653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1544a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1545a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1546a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1547a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1548a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1549653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1550653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1551a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1552a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1553a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1554a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1555a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1556a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1557a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1558a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1559a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1560285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1561285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1562285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1563a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1564a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1565a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1566a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1567a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1568f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1569a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1570f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1571a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1572a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1573a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1574a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1575a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1576a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1577a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1578a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1579a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1580a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1581a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1582a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1583a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1584a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1585a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1586a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1587a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1588ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov /** 1589ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 1590ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1591ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1592ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov public class GroupIdCacheEntry { 1593ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1594ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 1595ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1596ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1597ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1598a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 15993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 1600b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 160131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 16024097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1603f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1604315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1605315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov // We will use this much memory (in bits) to optimize the nickname cluster lookup 1606315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private static final int NICKNAME_BLOOM_FILTER_SIZE = 0x1FFF; // =long[128] 1607315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private BitSet mNicknameBloomFilter; 1608315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1609ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, SoftReference<String[]>> mNicknameClusterCache = Maps.newHashMap(); 1610ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 1611622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1612622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1613ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1614ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1615ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // is a list of groups with this group id. 1616ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1617ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 1618622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1619f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1620a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1621a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 162220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 16231129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private CharArrayBuffer mCharArrayBuffer = new CharArrayBuffer(128); 162420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1625ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 162673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1627ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<Long, Account> mInsertedRawContacts = Maps.newHashMap(); 1628b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1629a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private HashSet<Long> mDirtyRawContacts = Sets.newHashSet(); 1630b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1631de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 16321a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 16331a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 163481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 163581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 16364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 16374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1638de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1639ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1640ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1641ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1642ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1643ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1644ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1645ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 164635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1647ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 1648de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1649b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1650a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1651b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1652d076a108d58b30591f197e1b90fa8de60999c499Dmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper); 16530e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1654a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1655b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 1656653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1657c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1658653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1659653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1660653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1661653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1662653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1663c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1664653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1665653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1666653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1667653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1668653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1669653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1670653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1671653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1672653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1673653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1674653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1675ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate = db.compileStatement( 1676ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton "UPDATE " + Tables.CONTACTS + 1677ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton " SET " + Contacts.LAST_TIME_CONTACTED + "=? " + 1678ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton "WHERE " + Contacts._ID + "=?"); 1679a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 168025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate = db.compileStatement( 168125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 168225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " SET " + RawContactsColumns.DISPLAY_NAME + "=?," 168325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov + RawContactsColumns.DISPLAY_NAME_SOURCE + "=?" + 168425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 16853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1686a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate = db.compileStatement( 1687a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.CONTACTS + 1688a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1689a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1690a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1691a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1692a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1693a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1694a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1695a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1696a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1697a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 16980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 16990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1700a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " LIMIT 1)" + 1701a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1702e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1703622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Locale locale = Locale.getDefault(); 170428f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 170528f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 170628f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 170728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 1708622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey context.getString(com.android.internal.R.string.common_name_conjunctions), 1709622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey locale); 1710f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 1711622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mPostalSplitter = new PostalSplitter(locale); 17124097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1713f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1714f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1715f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1716f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1717f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1718f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1719f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1720a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert = db.compileStatement( 1721a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1722a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 1728a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1729a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace = db.compileStatement( 1730a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1731a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 17330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1738a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1739a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp = db.compileStatement( 1740a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 17420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 1743a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 17440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 17450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 17460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate = db.compileStatement( 17470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 17490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 17500a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 17510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1752a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1753a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete = db.compileStatement( 1754a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1755a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1756a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 17573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 17583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1759e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 17603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 17613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 176267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 176367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 17643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 17653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 176614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 17673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 17683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1769622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1770622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1771a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1772a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 17733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 17743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1775568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 17763d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1777568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1778c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov verifyAccounts(); 177970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 1780f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1781f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 17821129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdStructuredName = mDbHelper.getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE); 17831129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdOrganization = mDbHelper.getMimeTypeId(Organization.CONTENT_ITEM_TYPE); 17841129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdNickname = mDbHelper.getMimeTypeId(Nickname.CONTENT_ITEM_TYPE); 17851129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdPhone = mDbHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 1786315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov preloadNicknameBloomFilter(); 17871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 17884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 17894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1790c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 1791c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1792c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1793c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 1794c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 179531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1796de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1797b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1798b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 179931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 180031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1801013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1802013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1803013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1804013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 18053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 18063d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 18083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18093d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1810568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1811568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1812568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1813568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1814568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1815568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1816568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1817568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1818568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1819ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1820568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1821568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1822568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1823568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1824568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1825d076a108d58b30591f197e1b90fa8de60999c499Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1826568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1827568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1828568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1829568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1830568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1831ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1832ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1833568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1834568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1835568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1836568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1837568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1838568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1839568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 18403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1841568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1842568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 18433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 18453d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 18463d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 18473d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 18483d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 18493d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 18503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 18533d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1854568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 18550e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 18563d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 18573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 18583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 18590e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(aggregatorEnabled); 18603d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 18613d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 18623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 18633d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 18643d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1867a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1868a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1869a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1870a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1871b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 1872a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1873a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1874568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1875568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 1876568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1877568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1878568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1879568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1880568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1881568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 1882ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 1883ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 1884ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 1885ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 1886ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 1887ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1888ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 1889ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 189081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 1891ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1892ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1893568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1894568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1895568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1896568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1897568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1898568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1899568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1900568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1901568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1902568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1903568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1904568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1905568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1906568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1907568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1908568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1909568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 1910568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1911568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1912568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1913568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1914568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1915568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1916568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 1917568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1918568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1919568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1920568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1922285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1923bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1924b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1925b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1926285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 19271ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1928b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1929b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1930b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1931b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 1932285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 1933b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 1934df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 1935a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.clear(); 1936285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1937285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1938285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1939285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 19401129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 1941bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1942b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1943b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1944285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1945b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 19461ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 19471a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 19481a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 1949b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 19501a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 1951b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1952b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1953b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1954bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1955b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1956b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 19571129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 195808e42c9c153a60bf2e7c71dd40bf84bb5fc93555Dmitri Plotnikov for (long rawContactId : mInsertedRawContacts.keySet()) { 1959d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(mDb, rawContactId); 1960d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mContactAggregator.onRawContactInsert(mDb, rawContactId); 1961285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1962b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1963a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov if (!mDirtyRawContacts.isEmpty()) { 1964a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 1965a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 1966a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mDirtyRawContacts); 1967a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 1968a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 1969a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 1970a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1971b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 1972a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 1973a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 1974a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mUpdatedRawContacts); 1975a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 1976a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 1977b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1978b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1979b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 1980b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 1981b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().update(mDb, id, entry.getValue()); 1982b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1983b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1984b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1985b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1986b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1987a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 1988a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 1989a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 1990a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 1991a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private void appendIds(StringBuilder sb, HashSet<Long> ids) { 1992b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 1993a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 1994b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1995a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1996a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 1997285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1998285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1999285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2000cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 200181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 200281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 200381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 200481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 200581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 200681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 200781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2008cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2009568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2010285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 2011ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return mInsertedRawContacts.containsKey(rawContactId); 2012285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2013285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 20143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 20153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 20163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 20173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 20183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 20193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 20213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 20234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2024de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2025bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 20261129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2027b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2028f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2029f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2030f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2031f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2032a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2033a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 203435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2035a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 203635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2037b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 203835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 203935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2040d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2041d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 20426bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 20436bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 20446bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 20455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2046f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertRawContact(uri, values); 2047f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2048a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2049a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2050a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 20515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 20525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2053f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2054f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2055a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2056a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2057a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2058a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2059f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2060f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2061a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2062a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2063a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2064ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2065f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2066f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2067ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2068ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2069ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2070eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 20715aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 207243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2073eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2074eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2075eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 207682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 207782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 20781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 20791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20801f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2081a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 208281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2083f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2084a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2085a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 20867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 20877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 20887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 20897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2090de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2091a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2092a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2093a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2094035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 2095035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 2096f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the ContentValues to read from and update 2097f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the explicitly provided Account 2098f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @return false if the parameters are inconsistent 20997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2100f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private boolean resolveAccount(Uri uri, ContentValues values) { 2101f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2102f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2103f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2104f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) { 2105f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = null; 2106f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = null; 2107f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2108f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2109f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2110f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2111f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2112f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (TextUtils.isEmpty(valueAccountName) && TextUtils.isEmpty(valueAccountType)) { 2113f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2114f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2115f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 2116f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (accountName != null && !accountName.equals(valueAccountName)) { 2117f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return false; 2118f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2119f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2120f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (accountType != null && !accountType.equals(valueAccountType)) { 2121035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 2122035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2123f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2124f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2125f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2126f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2127f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2128f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) { 2129f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = null; 2130f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return true; 2131035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2132f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2133f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2134f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2135f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2136f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2137035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2138f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2139035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 21407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 21427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2143d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 21446bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 21456bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 21466bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 21476bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2148d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2149de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 21506bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 21516bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 21526bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2153a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2154a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2155f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2156f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2157a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2158a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2159f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertRawContact(Uri uri, ContentValues values) { 2160f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2161f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2162f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2163f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2164f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (!resolveAccount(uri, mValues)) { 21657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 21667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 21683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 21693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2170f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 21713d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 21723d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2173f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 2174023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 2175285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2176285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2177f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mInsertedRawContacts.put(rawContactId, mAccount); 2178f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2179023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2180a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2181a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2182a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2183a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2184a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2185a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2186a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2187a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2188f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2189a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2190de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2191de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 219267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2193de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 219420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2195de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2196de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2197de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2198b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2199de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2200de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2201508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2202de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2203de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2204de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2205de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2206de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 22074097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2208b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2209de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2210a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2211a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2212a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2213f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2214de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2215a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2216b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2217a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2218a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2219a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2220a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2221a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 22224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 22248e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 22258e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 22268e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 22278e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 22288e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2229b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2230f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 22318e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 22328e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 22338e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 22348e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2235421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 2236f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22378e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 22388e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 22398e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2240b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2241f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 22428e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 22438e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 22448e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2245f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22468e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2247f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2248c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 2249b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 22508e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2251f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22528e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2253f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2254f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2255f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2256a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 22575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 22589261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 22599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 22605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 22619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 22629261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 22639261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 22649261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 22659261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 2266ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId, 2267ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Account account) { 2268ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2269ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (account == null) { 22704da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 2271ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 22724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov RawContacts._ID + "=?", mSelectionArgs1, null, null, null); 2273ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov try { 2274ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2275ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = c.getString(RawContactsQuery.ACCOUNT_NAME); 2276ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = c.getString(RawContactsQuery.ACCOUNT_TYPE); 2277ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 2278ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov account = new Account(accountName, accountType); 2279ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 22809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2281ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } finally { 2282ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov c.close(); 22839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2285ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 22869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 22879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 2288ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov + "has a sourceid the the contact must be associated with " 22899261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 22909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2292ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ArrayList<GroupIdCacheEntry> entries = mGroupIdCache.get(sourceId); 2293ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entries == null) { 2294ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries = new ArrayList<GroupIdCacheEntry>(1); 2295ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.put(sourceId, entries); 2296ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2297ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2298ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int count = entries.size(); 2299ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov for (int i = 0; i < count; i++) { 2300ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = entries.get(i); 2301ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entry.accountName.equals(account.name) && entry.accountType.equals(account.type)) { 2302ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 2303ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2304ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2305ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2306ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = new GroupIdCacheEntry(); 2307ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountName = account.name; 2308ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountType = account.type; 2309ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.sourceId = sourceId; 2310ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries.add(0, entry); 2311ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 23129261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 23135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 2314ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 23159261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2316df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 23179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 2318ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2319ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = c.getLong(0); 23209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 23219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2322df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2323df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 23249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 23259261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 23269261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 23279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 23289261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 23299261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2330ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = groupId; 23319261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23329261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 23339261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 23349261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2335ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2336ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 23379261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23389261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2339d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private interface DisplayNameQuery { 23401129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov public static final String RAW_SQL = 23411129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov "SELECT " 23421129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + DataColumns.MIMETYPE_ID + "," 23431129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.IS_PRIMARY + "," 23441129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.DATA1 + "," 23451129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Organization.TITLE + 23461129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " FROM " + Tables.DATA + 23471129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " WHERE " + Data.RAW_CONTACT_ID + "=?" + 23481129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " AND (" + Data.DATA1 + " NOT NULL OR " + 23491129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Organization.TITLE + " NOT NULL)"; 2350d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2351d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int MIMETYPE = 0; 2352d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int IS_PRIMARY = 1; 2353d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int DATA = 2; 2354d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int TITLE = 3; 2355d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2356d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2357d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov /** 2358d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * Updates a raw contact display name based on data rows, e.g. structured name, 2359d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * organization, email etc. 2360d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov */ 2361d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 2362d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov String bestDisplayName = null; 2363d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 2364d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 23651129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 23661129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Cursor c = db.rawQuery(DisplayNameQuery.RAW_SQL, mSelectionArgs1); 2367d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov try { 2368d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov while (c.moveToNext()) { 23691129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov int mimeType = c.getInt(DisplayNameQuery.MIMETYPE); 23701129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 23711129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov // Display name is at DATA1 in all type. This is ensured in the 23721129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov // constructor. 23731129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 23741129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA, mCharArrayBuffer); 23751129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (mimeType == mMimeTypeIdOrganization && mCharArrayBuffer.sizeCopied == 0) { 23761129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.TITLE, mCharArrayBuffer); 2377d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 23781129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 23791129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 23801129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov int source = getDisplayNameSource(mimeType); 23811129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (source > bestDisplayNameSource) { 2382d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov bestDisplayNameSource = source; 23831129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 23841129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 23851129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (source == bestDisplayNameSource 23861129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && source != DisplayNameSources.UNDEFINED) { 23871129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (mimeType == mMimeTypeIdStructuredName 23881129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov || c.getInt(DisplayNameQuery.IS_PRIMARY) != 0) { 23891129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayNameSource = source; 23901129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 23911129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 23921129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 2393d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2394d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2395d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2396d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2397d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } finally { 2398d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov c.close(); 2399d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2400d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2401d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov setDisplayName(rawContactId, bestDisplayName, bestDisplayNameSource); 2402d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2403d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 24041129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private int getDisplayNameSource(int mimeTypeId) { 24051129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (mimeTypeId == mMimeTypeIdStructuredName) { 24061129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.STRUCTURED_NAME; 24071129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdEmail) { 24081129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.EMAIL; 24091129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdPhone) { 24101129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.PHONE; 24111129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdOrganization) { 24121129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.ORGANIZATION; 24131129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdNickname) { 24141129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.NICKNAME; 24151129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else { 24161129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.UNDEFINED; 24171129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 24181129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 24191129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 24209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 242120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 242220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2423f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 242420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 242520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2426de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2427de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 242814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2429de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2430de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 243114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 243214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2433a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2434a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2435f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 243688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 2437a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2438a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2439a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 244088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 244120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 244220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2443de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 244420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 244520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 244620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 244720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 244820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 244988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 245088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 245188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 245220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2453f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 245488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 245588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 24564da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 24574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=?", 24584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 2459f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 246020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 246120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 246220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 246320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 246420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 246514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 246620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 246720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 246820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 246920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 247020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 247120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 247220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 247320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 247420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 24757a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 247620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 247720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 247820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2479a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2480a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 24818e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2482a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2483a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2484a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 24858e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 248620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 248720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 248820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 248920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 249020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 249120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2492ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2493ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2494f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2495f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2496f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2497f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2498f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (!resolveAccount(uri, mValues)) { 2499ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 2500ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2501ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2502ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 2503f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 250467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 2505f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 250667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 2507f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 2508ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2509f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2510f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 251173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 251273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2513f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 2514ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2515f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 25161a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2517ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2518ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2519ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2520ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2521ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 25225aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2523e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 25245aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 25251a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 25261a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2527e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 25281a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 2529e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2530e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2531e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2532ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 253382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 25341f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 253582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 253682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 25370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 25384dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 25394dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 25400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 254182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 25424dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 25434dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 25444dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 25454dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 25461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25471f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2548dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 2549dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 255082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 2551f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 2552dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 2553dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 2554dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2555f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "="); 2556f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(dataId); 25571f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 2558dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 2559dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 25600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 25610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 25620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 25630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2564dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 2565dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 2566dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2567dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 2568f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2569f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 2570f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 2571f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 2572f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2573f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 2574f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 2575f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (") 2576f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2577f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(",") 2578f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2579f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(")" + " AND " + Data.DATA1 + "="); 2580f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2581f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ((" + DataColumns.MIMETYPE_ID + "=") 2582f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2583f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2584f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol); 2585dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2586f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2587f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2588dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2589f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=") 2590f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2591f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append("))"); 2592dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 2593f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=") 2594f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2595f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2596f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol) 2597f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.DATA + "="); 2598f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2599dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2600f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2601f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2602dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2603dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 26041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 260582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 2606f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=") 260782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .append(values.getAsLong(StatusUpdates.DATA_ID)); 2608dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 260970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 2610f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 261170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 26121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 26131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2614de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 2615c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov mSb.toString(), null, null, null, 2616c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 26171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 261867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 26195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2620e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 26211f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 26221f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 26231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 26241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 26251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 262631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 262731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 262831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 26291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 26301f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 263182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2632a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2633a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2634a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2635a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2636a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2637a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2638a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 263982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2640a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2641a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 264282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 264382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 264482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 264582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 264682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2647a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 264882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 264982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 26501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2651a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2652a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2653a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2654e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 26550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 265682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 265782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 26580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 26590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 26600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 26610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 26620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 26630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 26640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 26650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 26660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 26670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 26680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 26690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2670a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 2671a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 2672a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 267382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 267482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 2675a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 2676a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 26770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 3, status); 26780a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 4, resPackage); 26790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 5, iconResource); 26800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 6, labelResource); 2681a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 2682a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 2683a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2684a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 2685a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 26860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 2, status); 26870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 3, resPackage); 26880a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 4, iconResource); 26890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 5, labelResource); 2690a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 2691a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 2692a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 26930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 2694a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 26950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 2, status); 2696a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 26970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 4, status); 2698a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 26990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 27000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 1, resPackage); 27010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 2, iconResource); 27020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 3, labelResource); 27030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 27040a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 2705a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2706e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2707e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2708bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2709a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2710a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 2711a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 2712a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 2713a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2714a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2715a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 27161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 27171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 27184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2719de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2720bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2721b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2722b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2723b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2724f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2725f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2726508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2727508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 272835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2729b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 273035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2731b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2732b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2733b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2734b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2735b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2736b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2737cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2738cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2739cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2740cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2741cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2742d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2743d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2744cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 27456bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 27466bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 27472e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 27482e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 27492e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 27502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 27512e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 27522e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 27532e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 27542e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 27552e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 27562e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 27572e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 27582e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 27592971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 27602971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 2761fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, 2762fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 2763e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 27642971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 27652971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 27662971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2767fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 2768fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 2769fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 27702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 27722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 27732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 27752971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 27775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 27782971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2779fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return deleteRawContact(rawContactId, mDbHelper.getContactId(rawContactId), 2780fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 2781508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2782508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 278320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2784f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2785944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2786f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 278720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 278820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 278948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 279048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 279148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 279248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2793508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2794f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 27954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 27964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 2797ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2798ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2799ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2800f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 28015aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 28022971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 28032971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 28042971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 28052971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 28062971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2807e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 28082971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 28092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 28105aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 28112971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 28122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 28132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 28142971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 281581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2816f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 281781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 28182971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2819508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2820508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2821eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 282243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 28235aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteSettings(uri, selection, selectionArgs); 2824eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2825eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 282682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 28270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 28281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 28291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 283081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 283181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 28323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 283381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2834508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 28354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 28364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 28371c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 2838ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 2839b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 284094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2841de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 284294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 284394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 284494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 284594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2846f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2847de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 284894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 284994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 285094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2851f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2852de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 285394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 285494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 28551a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 285694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 285794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 285894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 28595aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2860e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 28611a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2862e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2863e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2864e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2865cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 2866cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2867cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null); 2868cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2869cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2870cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2871cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 2872cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2873cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2874cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2875cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2876cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2877cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2878cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2879cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2880fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 28813389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 2882f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 288314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2884fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov int count = mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 2885fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForContact(mDb, contactId); 2886fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 288733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2888b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 2889cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 289033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 289133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 289233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 28930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 28949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 28959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 28969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 28979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 28989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 28999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 29009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 29019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 29020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 29030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2904cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 290581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 290681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 2907cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 2908cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 2909cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2910cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2911cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2912cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2913cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 2914cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2915cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 29164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2917de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2918de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 2919bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2920b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2921b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2922b5a4add17815167d20a90645779df34cdf45280dFred Quintana 292335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 292400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 292500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 2926b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 2927b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 29281129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 2929b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 2930b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 2931b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2932b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2933f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2934f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 293500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 293635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2937b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2938b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 2939b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2940b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 2941b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 2942b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2943b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2944b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2945b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2946b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 2947b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 294835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2949d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 29508c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 295100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 295200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 295300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2954d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 29558c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 2956c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2957c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2958c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 29592e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 29602e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 29612e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 29622e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 29632e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 29642e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 29652e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 29662e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 29672e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 29688c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 29692e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 29702e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 29712e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 29727d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 29737d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 29747d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 29757d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 29767d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 29777d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 29787d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 29797d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 29807d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 29817d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 298220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2983944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2984f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 298581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2986f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 298781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 298820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 298920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2990c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 299148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 299248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 299348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 299448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2995f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 299681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2997f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 299881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 299900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 300000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 30017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 30025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 30035ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 30044529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 30057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 30067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 30077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 30085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 300933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 30104529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 30114da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 30124da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 30134529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 30144529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 30154da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 30164da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1); 30174529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 30187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 30197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 30207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3021ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 30225aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3023f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 302481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3025f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 302681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3027ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3028ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3029ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3030ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3031ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 30324da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 30334da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 303473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 30355aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 30365aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 303781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3038f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 303981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3040ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3041ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3042ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3043127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 3044de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 3045b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3046b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3047b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3048eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 30495aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateSettings(uri, values, selection, selectionArgs); 305043880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3051eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3052eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3053eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 30549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 30559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 30569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 30579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 305981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 306081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 3061f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 306281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 306300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 306400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 306500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 30664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 30674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 30689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 30699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 30709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 30719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 30729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 30739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 30749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 30759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 30769705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 30779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 30789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 30799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 30819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 30829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 30839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 30849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 30859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 30869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 30889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 30899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 30909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 30929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 30939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 30949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 30959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 30969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 30979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 30989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 30999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 31009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 31019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 31029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 31039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 31049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 31059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 31069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 31079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 31089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 31099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 31109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 31119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 31129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 31139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 31149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 31159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 31169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 31179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 31189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 31199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 31209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 31219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 31229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 31239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 31249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 31255aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 3126f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 312773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3128ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3129ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 313073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 3131f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 313273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 313373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 313473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 313573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 313673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 313773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 313873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 313973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3140ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 31411a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 31421a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 314394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 31446ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 31451129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 31466ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi final long groupId = ContentUris.parseId(uri); 31474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(groupId); 31486ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 31494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Groups.ACCOUNT_TYPE}, Groups._ID + "=?", mSelectionArgs1, null, 31506ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 31516ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 31526ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 31536ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 31546ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 31556ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 31566ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 31576ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 31586ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 3159ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 31606ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 31616ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 31626ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 31636ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 31646ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 31656ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 31666ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 31676ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 316894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 316994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 317094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 3171b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 3172b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 3173e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 31741a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 31751a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3176e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3177e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3178e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3179e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 31804529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 31814529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 31824529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 31834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 31844529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 318573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 31864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3187b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 318851bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 31894529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 31904529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 31914529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 31924529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 31934529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 31944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 31954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 31964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 31974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 31984529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 31994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 32004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 32014529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 32024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 32034529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 320419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final String selection = RawContacts._ID + " = " + rawContactId; 320519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 320619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 320719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 3208ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 3209ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 321019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 321119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 321219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka null, null, null, null); 321319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 321419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 321519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 3216ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 3217ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 321819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 321919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 322019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 322119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 322219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 322319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 322419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 322519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int count = mDb.update(Tables.RAW_CONTACTS, values, selection, null); 32265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3227433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 32284529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3229433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3230285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 3231285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateLookupKey(mDb, rawContactId); 3232285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 323319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 323419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 3235ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.put(rawContactId, new Account(accountName, accountType)); 323619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 32375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 32385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 323933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 324033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3241321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3242f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 324320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 324420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 324520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 32465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 324720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 324820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 324920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 325020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 325120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3252b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 325320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 325420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 325570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 325670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 325720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 325820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 325920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 326070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 326120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 326270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 326320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 326470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 326520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 326670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 326720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 326820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3269653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 327020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3271653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3272653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 327314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 3274653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 3275653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 3276f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 327720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3278653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 3279653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 328020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 328120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3282653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 328320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 328420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3285f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 3286653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 3287653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 3288321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3289653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 329014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 3291a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3292f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana rowHandler.update(mDb, values, c, callerIsSyncAdapter); 32938e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 3294a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 3295a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 3296a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 32978e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 3298653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 3299321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3300321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 33018c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 33028c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 33038c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 3304b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 33058c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 33068c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 33078c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 33088c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 33098c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 33108c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 33118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 33128c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 33138c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 33148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 33158c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 33168c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 33178c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 33188c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 33198c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 33208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 3321d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 33228c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3323b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3324d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3325b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 3326d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3327b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 3328d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3329b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3330d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3331b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3332d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 3333d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3334d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 33358c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 3336d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 3337d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3338d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 33398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 3340c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 33418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3342c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 3343c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 33444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 33454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?", mSelectionArgs1); 33468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 33478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 33488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 33498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3350b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 33518c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3352b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 33538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3354b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 33558c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3356b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 33578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3358b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 33598c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 33608c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 33619b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori int rslt = mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 33629b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 33639b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 33649b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 33659b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 33669b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 33679b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 3368f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3369d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3370ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton public void updateContactLastContactedTime(long contactId, long lastTimeContacted) { 3371ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 3372ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.bindLong(2, contactId); 3373ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.execute(); 3374d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3375d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3376127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 3377127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 33780c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 33790c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 338080c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 33810c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 33820c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 33830c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 33840c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 33850c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 33860c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 33870c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 3388b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3389127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 33900c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 33914da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 33924da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 33930c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 33944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 33954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 33960c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 33976bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 33986bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 33990c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 34000c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 34010c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 34020c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 3403127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 3404127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 34053389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3406dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 3407dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 3408dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 3409b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 34100c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 34110c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 3412b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId2 = mDbHelper.getContactId(rawContactId2); 34130c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 3414127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3415127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 3416127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 3417127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3418b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3419b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 342070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 3421b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 342270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (mDb == null) return; 342370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 3424627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 3425627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov boolean hasUnassignedContacts[] = new boolean[]{false}; 342670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 342770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 3428627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3429627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.RAW_CONTACTS, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE); 3430627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3431627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.GROUPS, Groups.ACCOUNT_NAME, Groups.ACCOUNT_TYPE); 3432627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3433627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.SETTINGS, Settings.ACCOUNT_NAME, Settings.ACCOUNT_TYPE); 343448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3435627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 3436627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // in the existingAccounts set will be extra accounts whose data must be deleted. 3437627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 3438627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 3439627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 344070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 344170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 344270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 34435f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 3444627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 3445627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3446627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 3447627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 3448627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 3449627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3450627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 3451627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 3452627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "SELECT " + RawContacts._ID + 3453627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 3454627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3455627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 3456627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3457627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 3458627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3459627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 3460627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3461627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 3462627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 3463627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 3464627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3465627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3466627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (hasUnassignedContacts[0]) { 3467627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3468627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Account primaryAccount = null; 3469627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 3470627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (isWritableAccount(account)) { 3471627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov primaryAccount = account; 3472627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov break; 3473627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3474627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3475627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3476627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (primaryAccount != null) { 3477627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {primaryAccount.name, primaryAccount.type}; 3478627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3479627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3480627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 3481627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + RawContacts.ACCOUNT_NAME + "=?," 3482627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=?" + 3483627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + 3484627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL", params); 3485627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3486627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // We don't currently support groups for unsynced accounts, so this is for 3487627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // the future 3488627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3489627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.GROUPS + 3490627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + Groups.ACCOUNT_NAME + "=?," 3491627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + Groups.ACCOUNT_TYPE + "=?" + 3492627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " IS NULL" + 3493627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " IS NULL", params); 3494627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 349570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3496627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3497b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 349870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 349970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 350070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 350170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 350270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3503619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3504619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3505627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 3506627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 3507627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov private void findValidAccounts(Set<Account> validAccounts, boolean[] hasUnassignedContacts, 3508627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String table, String accountNameColumn, String accountTypeColumn) { 3509627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Cursor c = mDb.rawQuery("SELECT DISTINCT " + accountNameColumn + "," + accountTypeColumn 3510627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + " FROM " + table, null); 3511627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 3512627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 3513627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (c.isNull(0) && c.isNull(1)) { 3514627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov hasUnassignedContacts[0] = true; 3515627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } else { 3516627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 3517627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3518627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3519627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 3520627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 3521627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3522627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3523627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3524627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov /** 3525622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 3526622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 352767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 352867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 352967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 353067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 353167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 353267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 353367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 353467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 353567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 353667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 353767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 353867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 3539dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 3540622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 3541dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 3542dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 3543622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3544622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3545dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 3546622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3547622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 35484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 35494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 35504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 3551bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3552bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3553bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 35540b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 3555b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 355635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3557d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 35581f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3559c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3560c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3561619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3562619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3563a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 35644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 356535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3566b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 356735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 356835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3569d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3570763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3571619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3572619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3573619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3574d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 35754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3576763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 35774da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 35784da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 35796bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 35806bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 35816bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 35825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 35835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 35845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 35855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 35865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 35875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 35885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 35905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 35915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 35925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3593763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 35944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String[] args; 35954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (selectionArgs == null) { 35964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[2]; 35974da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } else { 35984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[selectionArgs.length + 2]; 35994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 36004da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 36014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args[0] = String.valueOf(contactId); 36024da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args[1] = lookupKey; 36034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 36044da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 36055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 36065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 36075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 36085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 36115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3613763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 36144da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 36154da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 36164da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 36175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 36185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3620f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 3621f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 3622f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 3623763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 3624f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 36254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 36264da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 36274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 3628f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 3629f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 3630f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 3631ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3632763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3633ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 36344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 36354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3636e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 36375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 36384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sb.toString()); 3639ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3640ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3641ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3642ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3643ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3644ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 36454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3646ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3647d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 36484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 36494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3650e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 36515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 36524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 36534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 36544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3655763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3656ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 36575e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 36585e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 36595e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 36605e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar starredProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 36615e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar frequentProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 36625e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 36635e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 36644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 36654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 36664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3667d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 36685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 36695e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 36704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3671d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3672d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3673d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3674763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 36754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 36764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3677d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 36785e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 36795e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 3680d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3681d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 36824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3683d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3684d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3685d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3686d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 36874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 36884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3689d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3690d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3691d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3692d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3693d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3694d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3695ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3696763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3697b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 369871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 36994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3700b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3701b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3702b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3703b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3704d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 37054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 370682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 37074da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 37084da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 37096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 37106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 371100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3712ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 37133653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 371482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 37154da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 37164da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 37173653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 37183653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 37193653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 37203653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 37214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 372282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 372389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 37242815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 37252815f58f72f109790585931f601a63ddc02536a5Evan Millar } 37262815f58f72f109790585931f601a63ddc02536a5Evan Millar 372748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 372882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 37294da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 373048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 37314da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 373248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 373348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 373448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3735ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 373682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 373789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3738ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 37394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 37404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3741a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 37425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 37435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 37445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 37455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 37465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 37477318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 37485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 37495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 37505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 37515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 37525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 37535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 37545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 37555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 37565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 37575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 37585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 37595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 37605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 37615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 37625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 37635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 37645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 3765a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 3766ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 37675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3768a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3769a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3770a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 3771ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3772ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3773ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 37744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 377582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 377689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 37774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 37784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 37794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 378048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 378182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 37824da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 37834da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 37844da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 378548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 378648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 378748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 37885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 378982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 379089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 37914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 37924da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 37934da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Email.DATA + "=?"); 37944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3795ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3796ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3797ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 37985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 379982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 380007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 380107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 380207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 380307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 380407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 380507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 380607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 38075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 380807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 380907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 381007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 381107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 381207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 381307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 381407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 381507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 381607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 381707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 381807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.DATA1 + " LIKE "); 381907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 382020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 382120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 382220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 382307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 382407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov /* 382507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * Using a UNION instead of an "OR" to make SQLite use the right 382607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * indexes. We need it to use the (mimetype,data1) index for the 382707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * email lookup (see above), but not for the name lookup. 382807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * SQLite is not smart enough to use the index on one side of an OR 382907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * but not on the other. Using two separate nested queries 383007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * and a UNION between them does the job. 383107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov */ 383207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 383307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " UNION SELECT " + Data._ID + 383407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 383507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 383607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN "); 38377318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 383820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 38395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 3841a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 38425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 3844a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3845a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3846a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 38475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 38485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3850ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 385182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 385289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 385389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3854ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3855ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3856ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 385748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 385882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 38594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 386048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 386148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 38624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 386348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 386448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 386548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 38665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 3867763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 38684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 38694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 38704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 38715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 38725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 3873763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 38744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 38754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 38764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 38774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 38784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 38795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 38805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 388182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 38824da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 38834da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 3884e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3885e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3886e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 3887e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 388882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3889e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3890e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3891e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 38924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 389382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 38944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 38954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 3896a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3897a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3898a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3899a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 39004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3901a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 3902a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 3903a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 3904e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 3905a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3906a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3907e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 3908b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 3909e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 3910e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 3911e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 3912e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 3913e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 3914a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3915a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3916a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3917ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 3918b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3919ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 392089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3921ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3922ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3923ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3924ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3925b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3926ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 39274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 39284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 3929ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3930ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3931ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3932ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 3933b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 3934ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 393589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 393689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 3937ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3938ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3939ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3940b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 39410c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 3942b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 3943b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3944b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3945b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 394631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 3947d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 39482d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 39492d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 39502d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 39512d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 395231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 3953d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 3954d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 395531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 395631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 395731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 395831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3959763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 39607581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 39617581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 39622d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 396331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 396431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3965eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3966eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 3967eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 396889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3969e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3970e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 3971e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 3972b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 3973e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 397482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3975b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3976e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3977e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 397882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3979b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3980e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3981e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3982e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3983eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3984eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3985eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 398682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 39870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 39885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 39895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 39905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 399182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 39920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 39934da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 39944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 39955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 39965ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 39975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 3998c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 3999a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 4000c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4001c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4002c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 4003b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 4004b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh(db, contactId, projection); 4005c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4006c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 40071b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 4008b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 40091b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 40101b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 40111b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 40121b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 4013b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 40141b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 40151b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 40161b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 40171b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 40181b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 4019b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 40201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 40211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 40221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 40231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 40241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 4025b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 40261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 402771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 40281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 40291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 40301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 403146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 403246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 403346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 403446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 403546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 403646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 403746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 403846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 40394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 40404da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 404146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 404246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 404346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 40444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 4045f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 4046c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 40474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 40484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 40495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 40505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 40535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 40545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 4055038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 4056038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 4057038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 4058038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 40595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 40605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 40614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 40624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 40634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 40644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 40654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 40664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 40675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 40685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 40695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 40705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 40725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 40735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 40745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 40775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 40805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 40815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 40835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 40845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 40855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 40865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 40875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 40885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 40905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 40915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 40925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 40935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 40965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 40975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 40985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 40995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 41005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 41015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 41025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 41065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 41075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 41105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 41115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 41125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 41135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 41145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 41155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 41165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 41175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 41205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 41215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 41235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 41245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 41255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 41265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 41275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 41285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 41295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 41305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 41315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 41325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 41335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 41345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 41355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 41365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 41375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 41415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 41425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 41455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 41485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 41495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 41515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 41525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 41535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 41545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 41555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 41565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 41585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 41595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 41605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 41615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 41645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 41655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 41665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 41675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 41685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 41695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 41705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 41745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 41755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 41785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 41795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 41805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 41815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 41825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 41835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 41845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 41855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 41885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 41895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 41905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 41925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 41935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 41945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 41955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 41965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 41975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 41985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 41995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 42005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 42015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 42025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 42035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 42045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 42055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 42065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 42105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 42115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 42145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 42175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 42185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 42195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 42205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 42215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 42235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 42245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 42265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 42275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 42295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 42305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 42315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 42325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 42335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 42345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 42355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 42365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 42375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 42385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 42405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 42415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 42455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 42465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 42475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 42485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4251763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 4252763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 425382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4254763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4255f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4256763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4257763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4258d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4259763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4260763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 4261b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 426282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 426382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 426482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 426582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4266b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 426782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 426882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 426982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 427082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 427182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 42723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 42733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 4274a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 42753296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 427682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 427782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 427882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 427982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4280ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 4281763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 4282763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 4283763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4284f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4285763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4286763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4287d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4288763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4289763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 4290763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 4291763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 4292763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 4293763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4294763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 429546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 429646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana // Note: currently, "export only" equals to "restricted", but may not in the future. 429746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana boolean excludeRestrictedData = readBooleanQueryParameter(uri, 429846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.FOR_EXPORT_ONLY, false); 429946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 4300f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 430146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 430246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana if (requestingPackage != null) { 430346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana excludeRestrictedData = excludeRestrictedData 430446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 430546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 430646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 430746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setProjectionMap(sRawContactsEntityProjectionMap); 430846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 430946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 431046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 431182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 431282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 431382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4314d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa // Note: currently, "export only" equals to "restricted", but may not in the future. 4315763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = readBooleanQueryParameter(uri, 4316d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa Data.FOR_EXPORT_ONLY, false); 4317763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4318f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4319763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4320763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4321763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar excludeRestrictedData = excludeRestrictedData 4322d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4323763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4324763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4325763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getDataView(excludeRestrictedData)); 432682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 432782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 43283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated presence when requested 4329b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 433082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 43313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 433282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 433382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 433482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 43353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated status updates when requested 4336b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 433782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 433882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 433982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 434082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 434182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 43423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 43433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 434482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 43453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 4346ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 43473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 43483296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual presence when requested 43493296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 43503296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 43513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdates.DATA_ID + "=" 43523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 43533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 43543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 43553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual status updates when requested 43563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, 43573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS, 43583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_RES_PACKAGE, 43593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_ICON, 43603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_LABEL, 43613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_TIMESTAMP)) { 43623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 43633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 43643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 43653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 43663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 436782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 436882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 436982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 4370ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 4371ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 43720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 43730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 43740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4375b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 43760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 43770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4378b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 43790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 43800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 43810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 43820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 43830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4384b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 43850a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 43860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 43870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 43880a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 43890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 43900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 43910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 43920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 43930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 43940a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setTables(sb.toString()); 43950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 43960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 43970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 43984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 4399f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 4400f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 44014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 44024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 44034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 44044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 44054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 44064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 44074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 44084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 44094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 44104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4411e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 4412f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 4413f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 4414e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(accountName)) { 4415e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 4416e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4417e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 4418e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 4419e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 4420e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 4421e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 4422e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 4423e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4424e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 4425e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 4426e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 4427e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4428e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4429e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 44307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 4431c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 4432c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 4433c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 4434c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 4435c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 4436f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 4437f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String limitParam = getQueryParameter(uri, "limit"); 4438c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 4439c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4440c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4441c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 4442c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 4443c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 4444c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 4445c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4446c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4447c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4448c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 4449c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 4450c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4451c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4452c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4453c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4454c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 44555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 44565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 44575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 44585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 44595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 44605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 44615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 44625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 44635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 44645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 44655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 44665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 44675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 44695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 44705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 44715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 44735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 44745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 44765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 44775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 44795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 44805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 44825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 44835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 448500ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 4486d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 448770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 448870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 4489fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0"; 449070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 449170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 449270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 449370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 4494d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 449570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 449667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 44975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 44985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 4499619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4500619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4501619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4502b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 4503b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 4504b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 4505b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 4506d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 4507b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 4508b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 4509b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4510b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4511b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 4512b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 4513b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 45144da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=?"; 4515b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 45164da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, 45174da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 4518d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4519d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4520f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 4521d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 4522d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 452314b8a1243ab5c043b35e47527ca1c962064f3771Daisuke Miyakawa final String selection = Contacts._ID + "=" + contactId; 4524d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4525d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 4526d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 4527d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 4528d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 4529d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey outputRawContactsAsVCard(localStream, selection, null); 4530d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 4531d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4532b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4533b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 4534b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("No file at: " + uri); 4535b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4536b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4537b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4538d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 4539d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String VCARD_TYPE_DEFAULT = "default"; 4540d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4541d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4542d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 4543d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 4544d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4545d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 4546d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 4547d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 4548d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 4549d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4550d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 4551d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 4552d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4553d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 4554d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 4555d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 4556b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4557d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 4558d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 4559d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 4560d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4561d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 4562d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4563d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4564d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4565d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 4566d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 4567d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 4568d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4569d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 4570d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 4571d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 4572d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final VCardComposer composer = new VCardComposer(context, VCARD_TYPE_DEFAULT, false); 4573d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 4574d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4575f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 4576d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.init(selection, selectionArgs)) 4577d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 4578d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4579d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 4580d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 4581d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 4582d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4583d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4584d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 4585d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4586b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 45874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 45884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4589a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 45904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4591b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4592b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP: 4593be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 4594b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4595b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4596b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4597f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 4598f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 4599b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4600be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4601b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4602b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4603508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4604b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 460548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 460648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 460748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 460848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 460948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 461048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 461148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 461248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 461348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 461448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 461548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 461648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4617b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4618b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4619b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4620b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4621b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4622b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4623b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4624b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4625c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4626c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4627c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4628c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 462961efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 463061efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 46314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 46324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 46337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 463425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private void setDisplayName(long rawContactId, String displayName, int bestDisplayNameSource) { 46353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 463625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindString(1, displayName); 46373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 463825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindNull(1); 46393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 464025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(2, bestDisplayNameSource); 464125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(3, rawContactId); 464225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 46433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 46443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 464573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 464673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 464773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 464873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 4649a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.add(rawContactId); 465073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 465173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4652c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4653c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 4654c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 4655c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4656c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4657c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4658653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 4659c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 4660653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 4661653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 4662c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 4663c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4664c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 4665c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4666c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 4667c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 4668c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4669c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4670c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4671653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 4672c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 4673653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 4674653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 4675c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 4676c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4677ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4678f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 4679f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 4680f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4681f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4682f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4683f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); 4684f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (tokens.length == 0) { 4685f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4686f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4687f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4688f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String address = tokens[0].getAddress(); 4689f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int at = address.indexOf('@'); 4690f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (at != -1) { 4691f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov address = address.substring(0, at); 4692f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4693f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4694f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4695f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 4696f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4697f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4698f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4699f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 4700f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4701f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 4702f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 4703f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4704f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4705f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4706f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4707f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 4708f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4709f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4710a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 4711a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 4712a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 4713a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4714a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 4715a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4716a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 4717a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4718a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 4719a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4720a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4721f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4722f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name) { 4723f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name); 4724f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4725f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4726315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private interface NicknameLookupPreloadQuery { 4727315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 4728315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4729315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String[] COLUMNS = new String[] { 4730315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov NicknameLookupColumns.NAME 4731315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov }; 4732315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4733315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int NAME = 0; 4734315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4735315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4736315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov /** 4737315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * Read all known common nicknames from the database and populate a Bloom 4738315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * filter using the corresponding hash codes. The idea is to eliminate most 4739315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * of unnecessary database lookups for nicknames. Given a name, we will take 47403684089aba82df3f7a0c111e7c96ed8b0380e57aDmitri Plotnikov * its hash code and see if it is set in the Bloom filter. If not, we will know 4741315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * that the name is not in the database. If it is, we still need to run a 4742315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * query. 4743315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * <p> 4744315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * Given the size of the filter and the expected size of the nickname table, 4745315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * we should expect the combination of the Bloom filter and cache will 4746315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * prevent around 98-99% of unnecessary queries from running. 4747315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov */ 4748315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private void preloadNicknameBloomFilter() { 4749315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov mNicknameBloomFilter = new BitSet(NICKNAME_BLOOM_FILTER_SIZE + 1); 4750315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4751315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupPreloadQuery.TABLE, 4752315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov NicknameLookupPreloadQuery.COLUMNS, 4753315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov null, null, null, null, null); 4754315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov try { 4755315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int count = cursor.getCount(); 4756315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov for (int i = 0; i < count; i++) { 4757315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov cursor.moveToNext(); 4758315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String normalizedName = cursor.getString(NicknameLookupPreloadQuery.NAME); 4759315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int hashCode = normalizedName.hashCode(); 4760315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov mNicknameBloomFilter.set(hashCode & NICKNAME_BLOOM_FILTER_SIZE); 4761315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4762315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } finally { 4763315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov cursor.close(); 4764315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4765315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4766315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4767315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4768f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4769f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Returns nickname cluster IDs or null. Maintains cache. 4770f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4771f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4772315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int hashCode = normalizedName.hashCode(); 4773315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov if (!mNicknameBloomFilter.get(hashCode & NICKNAME_BLOOM_FILTER_SIZE)) { 4774315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov return null; 4775315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4776315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4777f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SoftReference<String[]> ref; 4778f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4779f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4780f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (mNicknameClusterCache.containsKey(normalizedName)) { 4781f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = mNicknameClusterCache.get(normalizedName); 4782f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (ref == null) { 4783f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return null; 4784f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4785f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = ref.get(); 4786f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4787f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4788f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4789f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (clusters == null) { 4790f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = loadNicknameClusters(normalizedName); 4791f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = clusters == null ? null : new SoftReference<String[]>(clusters); 4792f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4793f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNicknameClusterCache.put(normalizedName, ref); 4794f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4795f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4796f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4797f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4798f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4799315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private interface NicknameLookupQuery { 4800315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 4801315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4802315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String[] COLUMNS = new String[] { 4803315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov NicknameLookupColumns.CLUSTER 4804315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov }; 4805315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4806315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int CLUSTER = 0; 4807315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4808315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4809f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] loadNicknameClusters(String normalizedName) { 4810b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4811f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4812f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupQuery.TABLE, NicknameLookupQuery.COLUMNS, 4813f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.NAME + "=?", new String[] { normalizedName }, 4814f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov null, null, null); 4815f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov try { 4816f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int count = cursor.getCount(); 4817f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (count > 0) { 4818f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = new String[count]; 4819f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov for (int i = 0; i < count; i++) { 4820f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.moveToNext(); 4821f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters[i] = cursor.getString(NicknameLookupQuery.CLUSTER); 4822f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4823f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4824f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } finally { 4825f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.close(); 4826f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4827f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4828f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4829f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4830f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 4831f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4832f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 4833f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 4834f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4835f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4836f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4837f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 4838f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 4839f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 4840f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4841f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4842f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4843f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4844f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return ContactsProvider2.this.getCommonNicknameClusters(normalizedName); 4845f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4846f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4847f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4848f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4849f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 4850f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4851f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 4852f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 1, rawContactId); 4853f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 2, dataId); 4854f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 3, lookupType); 4855f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 4, name); 4856f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 4857f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4858f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4859f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4860f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 4861f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4862f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 4863f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupDelete, 1, dataId); 4864f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 4865f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4866f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 48672d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 4868d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4869d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 4870d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4871d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 4872d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 4873d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 4874d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 4875e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 4876d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN(" 4877d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 4878d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 4879d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NICKNAME + "," 4880d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.ORGANIZATION + "))"); 4881e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 4882e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 48835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 4884c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 48857318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam); 4886c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 4887c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4888c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 48897318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam) { 48907318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), true); 48915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 48925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 48935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 48947318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov boolean allowEmailMatch) { 4895d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4896dc947a9d03279eab0fb7c3b9d8ffbb492c1e2062Dmitri Plotnikov "SELECT " + NameLookupColumns.RAW_CONTACT_ID + 4897d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 4898d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 4899d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 49005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 4901a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 4902a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 4903a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 490420938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov + NameLookupType.ORGANIZATION); 490520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 490620938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 490720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 49087318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov sb.append("))"); 4909ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4910ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 49114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 49124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 49134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 49144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 4915b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 4916b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 4917b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 4918b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 4919b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 49204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 49214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 4922b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 4923b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4924b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4925caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 49265e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 49275e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 49285e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 49295e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 49305e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 49315e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 49325e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 49335e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 49345e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 49355e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 49365e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 4937caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 4938caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 4939caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 4940df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 4941df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 4942caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 4943caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 4944caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 4945caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 49466f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 4947caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 49486f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 4949caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 4950f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4951627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov protected boolean isWritableAccount(Account account) { 4952627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 4953627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4954627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 4955627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 4956627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov account.type.equals(sync.accountType)) { 4957627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov return sync.supportsUploading(); 4958627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4959627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4960627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 4961627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 4962627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4963627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov return false; 4964627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4965b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 4966f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 4967f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 4968f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4969f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 4970f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 4971f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 4972f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 4973f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 4974f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4975f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 4976f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 4977f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 4978f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 4979f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4980f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 4981f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4982f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 4983f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 4984f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 4985f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4986f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 4987f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 4988f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 4989f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 4990f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 4991f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 4992f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4993f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 4994f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 4995f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 4996f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 4997f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 4998f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 4999f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5000f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5001f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5002f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 5003f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 5004f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5005f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 5006f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 5007f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 5008f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 5009f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5010f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5011f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5012f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5013f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 5014f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5015f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 5016f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5017f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5018f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5019f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 5020f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 5021f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 5022f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5023f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5024f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5025f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 5026f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 5027f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 5028f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 5029f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 5030f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5031f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5032f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 5033f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 50344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 5035