ContactsProvider2.java revision c03e723e7b07434a3e60454606bc18e2df4ee06b
14f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/* 24f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Copyright (C) 2009 The Android Open Source Project 34f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 44f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 54f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * you may not use this file except in compliance with the License. 64f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * You may obtain a copy of the License at 74f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 84f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 94f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Unless required by applicable law or agreed to in writing, software 114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * See the License for the specific language governing permissions and 144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * limitations under the License 154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts; 1828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar 193de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.internal.content.SyncStateContentProviderHelper; 203de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 21b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 22b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 23b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 24b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkeyimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 26b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 27b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DisplayNameSources; 28b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 29b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 30b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 31b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 32b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NicknameLookupColumns; 33b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 34b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 35b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 36b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 37b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 38b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 39b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 40a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Lists; 41a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Maps; 42a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Sets; 433de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 44b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 45caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 465b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 47c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 48568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 49568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 506ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 5135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 5435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.Entity; 5567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.EntityIterator; 56568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 5867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 593de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.content.SharedPreferences.Editor; 60b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 62ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 63a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 64b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 65b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 68c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 706ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 71d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 72b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 730e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 74d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 753d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 76508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 773de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 783de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.LiveFolders; 793de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.OpenableColumns; 803de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.SyncStateContract; 81b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 823de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 833de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 843de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 853de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 863de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 873de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 8882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 90ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 91ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 95de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 96b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 974097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 9867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 99a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 100a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 101f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Token; 102f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer; 103c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 105d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 106b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 107d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 108d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 109f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport java.lang.ref.SoftReference; 1107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 112b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1130e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 115622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 116b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1170e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 118ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1245b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 125caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 126bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 127bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 128bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 130619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 131619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 132619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1440e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1450e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 146a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 148d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 149d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.TIMES_CONTACTED + " DESC, " 1509b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 151d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 152d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 154d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 155d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 156d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 165f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 1664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 17046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 1714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1726bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1736bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 174ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 17548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 17648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 17748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 17848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 17948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 18048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 18148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 18248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 183a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1846bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1856bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 186b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 187b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 188b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 18982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 19082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 1911f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 19231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 19331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 194eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 195eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 196ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 197ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 198ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 199ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 20035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 201b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 20235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 203c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 204c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 205c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2061b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2071b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2081b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2091b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2101b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 21146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 21246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 21367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private interface ContactsQuery { 2145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final String TABLE = Tables.RAW_CONTACTS; 2159261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 21667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2176cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2186cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 2196cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 220ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 221ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2225ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 22367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_NAME = 1; 22467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_TYPE = 2; 22567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 22667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 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 2433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private interface DisplayNameQuery { 24467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final String[] COLUMNS = new String[] { 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 249f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 250a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka Organization.TITLE, 2513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 0; 2543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 1; 255a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public static final int DATA = 2; 256a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public static final int TITLE = 3; 2573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 25914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 26067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 267f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 26888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 26988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 27088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 27188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 27288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 27388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 27488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 275f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 2763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 27814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 282f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 2833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 28514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 286321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 28720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 28820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 289321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 290321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 29120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 29220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 293f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 294f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private interface NicknameLookupQuery { 295f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 296f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 297f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] COLUMNS = new String[] { 298f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.CLUSTER 299f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov }; 300f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 301f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int CLUSTER = 0; 302f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 303f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 30419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 30519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 30619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 30719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 30819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.DELETED 30919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 31019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 31119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 31219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 31319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 31425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private static final HashMap<String, Integer> sDisplayNameSources; 3153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov static { 31625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources = new HashMap<String, Integer>(); 31725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(StructuredName.CONTENT_ITEM_TYPE, 31825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.STRUCTURED_NAME); 319a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sDisplayNameSources.put(Nickname.CONTENT_ITEM_TYPE, 320a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka DisplayNameSources.NICKNAME); 32125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Organization.CONTENT_ITEM_TYPE, 32225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.ORGANIZATION); 32325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Phone.CONTENT_ITEM_TYPE, 32425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.PHONE); 32525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Email.CONTENT_ITEM_TYPE, 32625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.EMAIL); 3273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 32831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 329c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 330df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 331caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 33271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 33371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 33471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 33571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 33671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 33771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 33871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 33971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 34071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 34171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 34271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 34371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 34471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 34571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 346038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 347038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 348e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 350f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 351f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final HashMap<String, String> sContactsVCardProjectionMap; 352ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 353d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 35446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** Contains the columns from the raw contacts entity view*/ 35546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final HashMap<String, String> sRawContactsEntityProjectionMap; 3564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 361e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 362ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 363ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 364ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 365ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 366373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 367b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 368eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 369eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 37082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 37182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 3721b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 375c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 376c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 378c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 379ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton /** Precompiled sql statement for incrementing times contacted for a contact */ 380ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton private SQLiteStatement mContactsLastTimeContactedUpdate; 3813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 38225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 38373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** Precompiled sql statement for marking a raw contact as dirty */ 38473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private SQLiteStatement mRawContactDirtyUpdate; 38582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 386a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 387f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 388f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 389a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 390a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 391a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 3920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 393a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 394a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 395f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 396f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 397f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 398f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 4004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 401a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 402d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 403d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 404d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 4053653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 4063653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 4072d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 4082d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 4093653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 4105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 4115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 4125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 413f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 4145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 415ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 416ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 4175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 4183653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 42246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 42346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 42446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 425b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4274f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 428ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 42948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 431ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 43348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 437ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 43848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 440ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 441ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 442ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 443ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 44435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 445b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 446b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 44735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 448a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 449b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 450b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 451b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 452b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 454eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 455eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 45682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 45782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 4581f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 459c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 460c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 461c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 462c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 463c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 464c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 465c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4691b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 4701b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 4711b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 4721b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 4731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 47419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 47519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 47619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 477038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 478038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 479e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 4814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 4824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 4834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 489f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 4904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 492f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 4933296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 4943296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 4953296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 4963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 4973296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 4983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 4993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 5003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 5013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 5023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 5033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 5043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 5053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 5063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 507f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap = Maps.newHashMap(); 508f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 509d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 510f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "0 AS " + OpenableColumns.SIZE); 5114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 5134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 5144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 5204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 5214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 5224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 5234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 5244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 5254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 5264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 5274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 5284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 5294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 5304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 5314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 5322815f58f72f109790585931f601a63ddc02536a5Evan Millar 5334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 5344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 5354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 5364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 5424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 5434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 5444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 5454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 5464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 5474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 5484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 5494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 5504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 5514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 5524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 5534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 5544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 5554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 5564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 56082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 5614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 56656d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 574a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 5754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 576a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 57746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana HashMap<String, String> columns; 57846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns = new HashMap<String, String>(); 57946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts._ID, RawContacts._ID); 58046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 58146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 58246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 58346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 58446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.VERSION, RawContacts.VERSION); 58546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 58646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DELETED, RawContacts.DELETED); 58746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 58846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 58946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 59046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 59146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 59246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.MIMETYPE, Data.MIMETYPE); 59346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA1, Data.DATA1); 59446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA2, Data.DATA2); 59546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA3, Data.DATA3); 59646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA4, Data.DATA4); 59746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA5, Data.DATA5); 59846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA6, Data.DATA6); 59946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA7, Data.DATA7); 60046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA8, Data.DATA8); 60146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA9, Data.DATA9); 60246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA10, Data.DATA10); 60346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA11, Data.DATA11); 60446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA12, Data.DATA12); 60546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA13, Data.DATA13); 60646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA14, Data.DATA14); 60746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA15, Data.DATA15); 60846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC1, Data.SYNC1); 60946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC2, Data.SYNC2); 61046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC3, Data.SYNC3); 61146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC4, Data.SYNC4); 61246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 61346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.STARRED, Data.STARRED); 61446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 61546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 61646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 61746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 61846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana sRawContactsEntityProjectionMap = columns; 61946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 6203296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 6213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 6223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 6233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 6243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 6253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 6263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 6303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 6323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 6333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 6353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.PRESENCE, 6363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 6373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS, 6383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 6393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 6403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 6423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_LABEL, 6443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_ICON, 6463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 6473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 6495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 6505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 6515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 6525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 6535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 6545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 6555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 6565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 6575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 6585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 6595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 6605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 6615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 6625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 6635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 6645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 6655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 6665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 6675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 6685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 6695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 6705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 6715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 6725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 6735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 6745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 6755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 6765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 6778f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 6785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 6795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 6805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 6815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 6825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 6835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 6845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 685a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 6865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 6875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 6885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 6893296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 6903296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 6913296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 6923296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 6933296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 6943296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 6953296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6973296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 6993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 7013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 7023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 7043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 7053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 7063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS, 7073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 7083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 7093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 7113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 7133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 7153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 7163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 717e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 718e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 719e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_ID + " AS " + PhoneLookup._ID); 72056d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 72156d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar Contacts.LOOKUP_KEY + " AS " + PhoneLookup.LOOKUP_KEY); 722e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 723e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + PhoneLookup.DISPLAY_NAME); 724e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 725e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 726e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 727e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 728e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " + PhoneLookup.TIMES_CONTACTED); 729e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 730e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_STARRED + " AS " + PhoneLookup.STARRED); 731e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 732e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 733e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 734e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.PHOTO_ID + " AS " + PhoneLookup.PHOTO_ID); 735e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 736e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " + PhoneLookup.CUSTOM_RINGTONE); 737e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 738e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.HAS_PHONE_NUMBER + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 739e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 740e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 741e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 742e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 743e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 744e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 745e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 746e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 747e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 7489261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 749ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 750ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 75189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 752035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 753035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 7549261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 7559261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 7569261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 75789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 758ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 75967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 760ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 7613cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 76294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 7633cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 76438446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 76589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 76689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 76789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 76889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 769ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 770ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 7716cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 772ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 773ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 774d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 775d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 776ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 777ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 778ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 779d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 780d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 781ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 782f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 783ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 784ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 785b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 786b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 787b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 788b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 7890c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 7900c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 791b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 792b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 793eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 794eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 795eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 796eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 797eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 798eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 799341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 800341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 801341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 802fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 803341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 804341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 805341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 80668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 80768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 80868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 80968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 81068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 811e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 81268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 81368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 81468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 815eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 816eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 817373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 8184dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 8190a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 8200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 82182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 82282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 82382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 82470c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 82570c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 82682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 82782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 82882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 82982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 8300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 8310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 8320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 8330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 8340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 83582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 83619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 8371b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 8381b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 8391b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 8401b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 8411b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 8421b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 8431b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 8441b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 8451b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 8461b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 8471b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 8484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 8494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 8503296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 8513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey map.put(toField, fromField + " AS " + toField); 8523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 8533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 8543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 8563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 8583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 860653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 8613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 8633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 864a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 865a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 866a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 867a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 868a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 869a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 870a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 871a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 8723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 874653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 875653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 876b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 877653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 878653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 879653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 880653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 8813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 8833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 885e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 886e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 887e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 888e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 889653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 890e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 891e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 892e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 8933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 8973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 8983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 899653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 900f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 90114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 90214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 903653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 904653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 905653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 906653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 907653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 908653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 909653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 910653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 911653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 912653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 913653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 914653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 915653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 916653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 917653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 918653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 919653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 920653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " = " + dataId, null); 921653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 922653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 923f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 924653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 925653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 9263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 92914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 93014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 93114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 9323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 9333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 9343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 9355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 9363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 9383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 9415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long newPrimaryId = findNewPrimaryDataId(db, rawContactId); 9423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (newPrimaryId != -1) { 94314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov setIsPrimary(rawContactId, newPrimaryId, getMimeTypeId()); 9443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected long findNewPrimaryDataId(SQLiteDatabase db, long rawContactId) { 948e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 949e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 9505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Cursor c = queryData(db, rawContactId); 9513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 952e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 95314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 954f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 955e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 956e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 957e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 958e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 9593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 9613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 9623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 963e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return primaryId; 964e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 965e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 966e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 967e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 968e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 969e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 970e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 971e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 9723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected Cursor queryData(SQLiteDatabase db, long rawContactId) { 97514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return db.query(DataDeleteQuery.TABLE, DataDeleteQuery.CONCRETE_COLUMNS, 97614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId + 97714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " AND " + MimetypesColumns.MIMETYPE + "='" + mMimetype + "'", 9783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov null, null, null, null); 9793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 98125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 9823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String bestDisplayName = null; 98325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 98425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov 98567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Cursor c = db.query(DisplayNameQuery.TABLE, DisplayNameQuery.COLUMNS, 9865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId, null, null, null, null); 9873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 9883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov while (c.moveToNext()) { 9893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String mimeType = c.getString(DisplayNameQuery.MIMETYPE); 990a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 991a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // Display name is at DATA1 in all type. This is ensured in the constructor. 992a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String name = c.getString(DisplayNameQuery.DATA); 993a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (TextUtils.isEmpty(name) 994a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka && Organization.CONTENT_ITEM_TYPE.equals(mimeType)) { 995a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka name = c.getString(DisplayNameQuery.TITLE); 9963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 997a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka boolean primary = StructuredName.CONTENT_ITEM_TYPE.equals(mimeType) 998a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || (c.getInt(DisplayNameQuery.IS_PRIMARY) != 0); 9993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 100001911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (name != null) { 100125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov Integer source = sDisplayNameSources.get(mimeType); 100201911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (source != null 100301911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov && (source > bestDisplayNameSource 100401911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov || (source == bestDisplayNameSource && primary))) { 100525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov bestDisplayNameSource = source; 10063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov bestDisplayName = name; 10073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 10123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 10133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 101525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov setDisplayName(rawContactId, bestDisplayName, bestDisplayNameSource); 1016285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1017285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateDisplayName(db, rawContactId); 1018285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 10193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1020a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1021a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1022a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return true; 1023a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1024622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1025622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1026622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 1027622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * as baseline, but augmented with any updates. 1028622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1029622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 1030622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 1031622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 1032622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=" + dataId, 1033622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey null, null, null, null); 1034622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 1035622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 1036622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 1037622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 1038622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.put(key, cursor.getString(i)); 1039622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1040622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1041622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 1042622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 1043622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1044622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 1045622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 1046622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 10503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 10523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1057622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 10583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 10603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1061622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 10623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 10655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1066622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 106714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 106814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 106914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1070f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1071f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 107225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 107314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 107414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 107514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 107614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 107714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1078f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1079622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1080622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1081cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1082622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1083622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 108414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1085f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 108614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1087f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 1088f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1089f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1090f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 109114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 109225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 109314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 109414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 109514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 109614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 109714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 109814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 109914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 110014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 110114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1102f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 110325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 110414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 11053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1108622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 11093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1110622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1111622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1112622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1113622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 11143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1115622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1116622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1117622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1118622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1119622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1120622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1121622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 112267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1123622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 112467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 112567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1126622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1127622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 11288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1129622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1130622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 113167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 113267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 113367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 113467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 113567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 113667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 11378c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1138622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 1139622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(name); 1140622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 1141622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1142622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1143622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1144622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1145622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1146622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1147622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1148622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1149622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1150622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1151622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1152622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1153622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1154622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1155622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1156622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1157622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1158622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1159622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1160622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1161f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1162622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1163622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1164622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1165f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1166622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1167622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1168622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1169622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1170622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1171622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1172622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1173622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1174622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1175622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1176622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1177622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1178622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1179622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1180622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1181622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1182622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1183622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 118467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 118567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 118667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 118767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1188622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1189622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1190622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1191622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1192622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1193622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 119467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 119567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 119667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1197622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1198622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1199622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 12003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 12053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 12073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 12083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 12103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 12113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 12123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 12133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1217622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1218622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1219622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1221622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1222622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1223f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1224622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1225622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1226622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1227f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1228622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1230622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1231622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1232622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1233622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1234622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1235622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1236622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1237622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 12383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1239622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1240622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1241622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1242622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1243622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 12483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 12503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 12513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1255a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1256a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1257a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1258a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1259a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 126025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1261a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1262a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 12633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 126614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1267f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1268a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1269a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1270a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 127114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 127214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1273f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 127414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 127525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1276a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 1277a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 127814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 127914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 128014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 128114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1282a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 128314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 128414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 128514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 128625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1287a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 128814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 128914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 129014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 12923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 12933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 12943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 12953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 12963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 12973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 12983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1300a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1301a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1302a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1303a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1304a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 13053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1307e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1308e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1309e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1310e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1311e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1312e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1313e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 13145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 131514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 131614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 131714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 131814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 131925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1320f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 132114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 132214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 132314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 132414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 132514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1326f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 132714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 132814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 132914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 133014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1331f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 133214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1333f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1334f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 133525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 133614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 133714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 133814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 133914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 134014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 134114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 134214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 134314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 134414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1345f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 134625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 134714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1348e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1349e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1350e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1351e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1352e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1353e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1354e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1355e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1356e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1357e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1358e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1359e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1360e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1361e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 136214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 136314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 136414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 136514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 136614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 136714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 136814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 136914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 137014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 137114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 137214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 137314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 137425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1375f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 137614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 137714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 137814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 137914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 138014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1381f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 138214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 138314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 138414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 138514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1386f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 138714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1388f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1389f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 139025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 139114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 139214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 139314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 139414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 139514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 139614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 139714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 139814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 139914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1400f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 140125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 140214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 140314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 140414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 140514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 14063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 14073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 14093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 14103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 14135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 14140b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 14150b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 14160b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 14170b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1418653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14190b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1420653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14210b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1422285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 142325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 14240b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 14250b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 14260b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1427653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1428653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1429653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1430653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1431653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1432f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 143314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 143414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 14350b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 14360b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 14370b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1438653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1439f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1440653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14410b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1442285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 144325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 14440b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 1445f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 14460b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 144714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 144814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 144914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 145014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 145114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 145214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 145314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 145414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 145514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 145614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1457285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 145825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 145914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1460653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1461653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1462653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1463e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1464e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1465e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1466e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1467653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1468653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1469653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1470e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1471653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1472653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1473e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1474653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 14755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1476653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1477e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 1478653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1479653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1480653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=" + dataId, null); 1481e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 14823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 14853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 14863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 14873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 14883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 14893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 14903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 14913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 14923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 14933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 14943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 14953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 14963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1500653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1501653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1502653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1503653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1504653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1505653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1506653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1507653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1508653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 15090be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 15100be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15110be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1512653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1513653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1514653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1515653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1516f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 151714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1518653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1519f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 15200be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15210be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 15220be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 15230be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 15240be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 15250be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 15260be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 15270be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15280be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 15290be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 15300be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 15310be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1532b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 15330be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1534b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 15350be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1536653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1537653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1538653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1539653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1540653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1541653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1542653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1543653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1544653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1545653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1546653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1547653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1548653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1549653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1550653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1551653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1552653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1553653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1554653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1555653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1556653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1557653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1558653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1559653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1560653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId); 1561653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1562653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1563653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1564653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1565a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1566a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1567a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1568a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1569a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1570653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1571653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1572a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1573a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1574a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1575a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1576a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1577a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1578a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1579a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1580a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1581285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1582285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1583285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1584a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1585a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1586a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1587a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1588a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1589f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1590a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1591f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1592a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1593a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1594a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1595a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1596a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1597a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1598a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1599a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1600a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1601a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1602a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1603a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1604a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1605a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1606a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1607a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1608a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1609a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 16103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 161153056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 1612b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 161331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 16144097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1615f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1616f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private HashMap<String, SoftReference<String[]>> mNicknameClusterCache = 1617f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov new HashMap<String, SoftReference<String[]>>(); 1618622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1619622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1620622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1621f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1622a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1623a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 162420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 162520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1626ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 162773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private boolean mImportMode; 162873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1629b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mInsertedRawContacts = Sets.newHashSet(); 1630b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1631b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1632de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 16331a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 16341a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 163581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 163681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 1637a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 163853056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 1639a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1640a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1641a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1642a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 1643a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 164453056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 164553056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 1646a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 16474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 16484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 16494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1650de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 165135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1652de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1653b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1654a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1655b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1656b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper, mAggregationScheduler); 16570e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1658a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1659b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 1660653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1661c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1662653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1663653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1664653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1665653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1666653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1667c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1668653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1669653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1670653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1671653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1672653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1673653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1674653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1675653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1676653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1677653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1678653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1679ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate = db.compileStatement( 1680ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton "UPDATE " + Tables.CONTACTS + 1681ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton " SET " + Contacts.LAST_TIME_CONTACTED + "=? " + 1682ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton "WHERE " + Contacts._ID + "=?"); 1683a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 168425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate = db.compileStatement( 168525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 168625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " SET " + RawContactsColumns.DISPLAY_NAME + "=?," 168725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov + RawContactsColumns.DISPLAY_NAME_SOURCE + "=?" + 168825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 16893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 169073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 169173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + RawContacts.DIRTY + "=1 WHERE " + RawContacts._ID + "=?"); 169273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1693a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate = db.compileStatement( 1694a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.CONTACTS 1695a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1696a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1697a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1698a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1699a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1700a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1701a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1702a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1703a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1704a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 17050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 17060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1707a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LIMIT 1)" 1708a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1709e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1710622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Locale locale = Locale.getDefault(); 171128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 171228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 171328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 171428f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 1715622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey context.getString(com.android.internal.R.string.common_name_conjunctions), 1716622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey locale); 1717f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 1718622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mPostalSplitter = new PostalSplitter(locale); 17194097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1720f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1721f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1722f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1723f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1724f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1725f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1726f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1727a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert = db.compileStatement( 1728a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1729a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 1735a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1736a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace = db.compileStatement( 1737a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1738a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 17400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1745a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1746a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp = db.compileStatement( 1747a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 17490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 1750a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 17510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 17520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 17530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate = db.compileStatement( 17540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 17560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 17570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 17580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1759a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1760a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete = db.compileStatement( 1761a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1762a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1763a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 17643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 17653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1766e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 17673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 17683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 176967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 177067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 17713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 17723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 177314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 17743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 17753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1776622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1777622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1778a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1779a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 17803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 17813d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1782568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 17833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1784568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1785c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov verifyAccounts(); 178670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 1787f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1788f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 17891f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 17904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 17914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1792c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 1793c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1794c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1795c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 1796c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 179731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1798de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1799b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1800b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 180131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 180231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1803285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov /* package */ ContactAggregationScheduler getContactAggregationScheduler() { 1804285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mAggregationScheduler; 1805285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1806285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1807013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1808013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1809013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1810013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 18113d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 18123d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18133d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 18143d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18153d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1816568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1817568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1818568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1819568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1820568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1821568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1822568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1823568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1824568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1825ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1826568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1827568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1828568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1829568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1830568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1831568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1832568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1833568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1834568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1835568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1836ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1837ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1838568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov scheduleContactAggregation(); 1839568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1840568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1841568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1842568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1843568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1844568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1845568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 18463d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1847568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1848568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 18493d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 18513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 18523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 18533d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 18543d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 18553d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 18563d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 18593d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1860568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 18610e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 18623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 186373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = true; 18643d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 18653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 18660e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(aggregatorEnabled); 18673d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 18683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 18693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 18703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 187173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } finally { 187273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = false; 18733d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18753d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1876a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1877a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 1878a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 1879a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 1880a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1881a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1882a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 1883a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1884a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1885a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1886a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1887a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1888a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1889b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 1890a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1891a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1892568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1893568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 1894568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1895568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1896568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1897568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1898568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1899568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 1900ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 1901ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 1902ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 1903ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 1904ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 1905ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1906ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 1907ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 190881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 1909ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1910ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1911568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1912568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1913568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1914568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1915568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1916568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1917568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1918568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1919568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1920568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1921568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1922568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1923568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1924568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1925568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1926568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1927568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 1928568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1929568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1930568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1931568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1932568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1933568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1934568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 1935568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1936568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1937568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1938568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1940285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1941bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1942b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1943b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1944285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 19451ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1946b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1947b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1948b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1949b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 1950285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 1951b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 1952df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 1953285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1954285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1955285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1956285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 1957bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1958b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1959b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1960285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1961b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 19621ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 19631a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 19641a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 1965b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 19661a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 1967b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1968b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1969b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1970bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1971b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1972b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1973b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long rawContactId : mInsertedRawContacts) { 1974b5a4add17815167d20a90645779df34cdf45280dFred Quintana mContactAggregator.insertContact(mDb, rawContactId); 1975285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1976b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1977b5a4add17815167d20a90645779df34cdf45280dFred Quintana String ids; 1978b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 1979b5a4add17815167d20a90645779df34cdf45280dFred Quintana ids = buildIdsString(mUpdatedRawContacts); 1980b5a4add17815167d20a90645779df34cdf45280dFred Quintana mDb.execSQL("UPDATE raw_contacts SET version = version + 1 WHERE _id in " + ids, 1981b5a4add17815167d20a90645779df34cdf45280dFred Quintana new Object[]{}); 1982b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1983b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1984b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 1985b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 1986b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().update(mDb, id, entry.getValue()); 1987b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1988b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1989b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1990b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1991b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1992b5a4add17815167d20a90645779df34cdf45280dFred Quintana private String buildIdsString(HashSet<Long> ids) { 1993b5a4add17815167d20a90645779df34cdf45280dFred Quintana StringBuilder idsBuilder = null; 1994b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 1995b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (idsBuilder == null) { 1996b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder = new StringBuilder(); 1997b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append("("); 1998b5a4add17815167d20a90645779df34cdf45280dFred Quintana } else { 1999b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(","); 2000b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2001b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(id); 2002b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2003b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(")"); 2004b5a4add17815167d20a90645779df34cdf45280dFred Quintana return idsBuilder.toString(); 2005285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2006285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2007285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2008cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 200981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 201081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 201181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 201281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 201381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 201481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 201581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2016cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2017568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2018568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected void scheduleContactAggregation() { 2019dee54bb86f3608730f0b9f37d8982a7f6b280a85Dmitri Plotnikov mContactAggregator.schedule(); 2020568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2021568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2022285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 2023285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mInsertedRawContacts.contains(rawContactId); 2024285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2025285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 20263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 20273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 20283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 20293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 20303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 20313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 20333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 20354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2036de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2037bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2038b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "insertInTransaction: " + uri); 2039b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2040f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2041f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2042f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2043f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2044a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2045a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 204635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2047a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 204835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2049b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 205035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 205135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2052d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2053d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 20546bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 20556bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 20566bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 20575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2058f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 2059d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov id = insertRawContact(values, account); 2060f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2061a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2062a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2063a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 20645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 20655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2066f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2067f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2068a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2069a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2070a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2071a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2072f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2073f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2074a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2075a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2076a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2077ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2078ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 20795aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertGroup(uri, values, account, callerIsSyncAdapter); 2080f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2081ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2082ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2083ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2084eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 20855aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 208643880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2087eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2088eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2089eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 209082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 209182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 20921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 20931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20941f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2095a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 209681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2097f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2098a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2099a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 21007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 21017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 21027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2104de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2105a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2106a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2107a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2108035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 2109035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 2110035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 2111035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 2112035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 21137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2114035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 2115035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 21166cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME); 21176cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2118035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 2119035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 2120035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 2121035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 2122035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2123035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 2124035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2125035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 2126df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_NAME, account.name); 2127df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_TYPE, account.type); 2128035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2129035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 21307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 21327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2133d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 21346bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 21356bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 21366bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 21376bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2138d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2139de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 21406bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 21416bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 21426bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2143a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2144a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2145a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2146f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 2147a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2148a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2149d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertRawContact(ContentValues values, Account account) { 2150a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 2151d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov overriddenValues.putNull(RawContacts.CONTACT_ID); 2152f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 21537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 21547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 21563d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 21573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 21583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov overriddenValues.put(RawContacts.AGGREGATION_MODE, 21593d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DISABLED); 21603d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 21613d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2162023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov long rawContactId = 2163023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, overriddenValues); 2164023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 2165285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2166285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2167285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.add(rawContactId); 2168023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2169a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2170a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2171a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2172a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2173a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2174a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2175a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2176a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2177f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2178a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2179de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2180de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 218167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2182de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 218320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2184de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2185de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2186de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2187b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2188de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2189de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2190508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2191de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2192de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2193de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2194de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2195de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 21964097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2197b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2198de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2199a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2200a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2201a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2202f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2203de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2204a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2205b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2206a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2207a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2208a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2209a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2210a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 22114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 22138e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 22148e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 22158e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 22168e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 22178e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2218b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2219f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 22208e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 22218e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 22228e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 22238e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2224421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 2225f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22268e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 22278e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 22288e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2229b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2230f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 22318e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 22328e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 22338e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2234f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22358e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2236f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2237c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 2238b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 22398e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2240f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22418e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2242f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2243f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2244f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2245a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 22465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 22479261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 22489261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 22495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 22509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 22519261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 22529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 22539261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 22549261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 22555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId) { 22569261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Account account = null; 22576cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts._ID + "=" 22585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId, null, null, null, null); 22599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 22609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 226167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountName = c.getString(ContactsQuery.ACCOUNT_NAME); 226267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountType = c.getString(ContactsQuery.ACCOUNT_TYPE); 22639261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 22649261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana account = new Account(accountName, accountType); 22659261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22669261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22679261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 22689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 22699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22709261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 22719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 22729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "has a sourceid the the contact must be associate with " 22739261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 22749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 22769261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 22775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 22786cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 22799261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2280df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 22819261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 22829261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 22839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return c.getLong(0); 22849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 22859261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2286df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2287df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 22889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 22899261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 22909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 22919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 22929261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 22939261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return groupId; 22959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 22979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 22989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22999261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 23019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 230220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 230320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2304f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 230520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 230620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2307de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2308de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 230914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2310de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2311de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 231214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 231314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2314a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2315a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2316f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 231788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 2318a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2319a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2320a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 232188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 232220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 232320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2324de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 232520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 232620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 232720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 232820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 232920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 233088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 233188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 233288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 233320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2334f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 233588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 233688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 233714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=" + dataId, null, 233814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov null); 2339f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 234020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 234120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 234220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 234320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 234420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 234514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 234620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 234720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 234820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 234920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 235020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 235120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 235220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 235320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 235420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 23557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 235620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 235720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 235820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2359a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2360a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 23618e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2362a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2363a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2364a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 23658e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 236620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 236720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 236820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 236920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 237020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 237120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2372ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2373ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2374b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, Account account, 2375b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov boolean callerIsSyncAdapter) { 2376ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 2377ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 2378ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 2379ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2380ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2381ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 238267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.RES_PACKAGE); 238367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 2384b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov overriddenValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 238567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 238667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.remove(Groups.RES_PACKAGE); 2387ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2388f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 238973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov overriddenValues.put(Groups.DIRTY, 1); 239073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 239173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2392ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey long result = mDb.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 2393ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 23941a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (overriddenValues.containsKey(Groups.GROUP_VISIBLE)) { 23951a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2396ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2397ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2398ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2399ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2400ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 24015aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2402e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 24035aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 24041a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 24051a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2406e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 24071a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 2408e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2409e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2410e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2411ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 241282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 24131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 241482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 241582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 24160a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 24174dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 24184dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 24190a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 242082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 24214dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 24224dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 24234dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 24244dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 24251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2427dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 2428dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 242982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 2430f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 2431dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 2432dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 2433dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2434f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "="); 2435f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(dataId); 24361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 2437dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 2438dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 24390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 24400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 24410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 24420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2443dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 2444dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 2445dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2446dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 2447f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2448f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 2449f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 2450f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 2451f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2452f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 2453f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 2454f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (") 2455f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2456f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(",") 2457f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2458f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(")" + " AND " + Data.DATA1 + "="); 2459f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2460f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ((" + DataColumns.MIMETYPE_ID + "=") 2461f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2462f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2463f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol); 2464dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2465f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2466f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2467dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2468f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=") 2469f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2470f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append("))"); 2471dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 2472f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=") 2473f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2474f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2475f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol) 2476f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.DATA + "="); 2477f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2478dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2479f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2480f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2481dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2482dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 24831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 248482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 2485f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=") 248682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .append(values.getAsLong(StatusUpdates.DATA_ID)); 2487dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 248870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 2489f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 249070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 24911f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 24921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2493de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 2494c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov mSb.toString(), null, null, null, 2495c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 24961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 249767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 24985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2499e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 25001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 25011f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 25021f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 25031f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 250531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 250631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 250731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 25081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 251082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2511a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2512a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2513a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2514a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2515a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2516a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2517a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 251882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2519a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2520a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 252182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 252282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 252382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 252482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 252582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2526a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 252782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 252882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 25291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2530a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2531a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2532a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2533e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 25340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 253582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 253682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 25370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 25380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 25390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 25400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 25410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 25420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 25430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 25440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 25450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 25460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 25470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 25480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2549a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 2550a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 2551a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 255282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 255382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 2554a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 2555a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 25560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 3, status); 25570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 4, resPackage); 25580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 5, iconResource); 25590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 6, labelResource); 2560a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 2561a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 2562a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2563a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 2564a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 25650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 2, status); 25660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 3, resPackage); 25670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 4, iconResource); 25680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 5, labelResource); 2569a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 2570a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 2571a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 25720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 2573a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 25740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 2, status); 2575a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 25760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 4, status); 2577a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 25780a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 25790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 1, resPackage); 25800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 2, iconResource); 25810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 3, labelResource); 25820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 25830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 2584a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2585e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2586e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2587bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2588a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2589a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 2590a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 2591a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 2592a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2593a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2594a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 25951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 25974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2598de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2599bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2600b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2601b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2602b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2603f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2604f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2605508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2606508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 260735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2608b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 260935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2610b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2611b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2612b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2613b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2614b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2615b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2616cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2617cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2618cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2619cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2620cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2621d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2622d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2623cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 26246bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 26256bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 26262e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 26272e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 26282e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 26292e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 26302e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 26312e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 26322e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26332e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 26342e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 26352e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 26362e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26372e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 26382971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 26392971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 26402971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2641e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 26422971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 26432971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 26442971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2645f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana numDeletes += deleteRawContact(rawContactId, callerIsSyncAdapter); 26462971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26472971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 26482971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 26492971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26502971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 26512971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26522971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 26535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 26542971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2655f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteRawContact(rawContactId, callerIsSyncAdapter); 2656508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2657508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 265820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2659f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2660944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2661f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 266220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 266320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 266448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 266548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 266648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 266748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2668508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2669f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2670f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteData(Data._ID + "=" + dataId, null, callerIsSyncAdapter); 2671ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2672ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2673ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2674f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 26755aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 26762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26772971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 26782971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 26792971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 26802971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2681e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 26822971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 26832971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 26845aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 26852971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26862971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 26872971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 26882971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 268981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2690f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 269181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 26922971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2693508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2694508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2695eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 269643880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 26975aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteSettings(uri, selection, selectionArgs); 2698eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2699eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 270082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 27010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 27021f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 27031f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 270481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 270581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 27063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 270781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2708508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 27094f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 271146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static boolean readBooleanQueryParameter(Uri uri, String name, boolean defaultValue) { 27122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final String flag = uri.getQueryParameter(name); 27132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return flag == null 27142971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana ? defaultValue 27152971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana : (!"false".equals(flag.toLowerCase()) && !"0".equals(flag.toLowerCase())); 271694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 271794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 27185aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 2719b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 272094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2721de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 272294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 272394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 272494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 272594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2726f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2727de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 272894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 272994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 273094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2731f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2732de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 273394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 273494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 27351a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 273694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 273794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 273894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 27395aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2740e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 27411a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2742e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2743e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2744e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2745cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 2746cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2747cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null); 2748cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2749cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2750cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2751cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 2752cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2753cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2754cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2755cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2756cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2757cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2758cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2759cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2760f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana public int deleteRawContact(long rawContactId, boolean callerIsSyncAdapter) { 2761f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 276214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2763de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 276433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2765b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 2766cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 276733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 276833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 276933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 27700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 27710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO delete from both tables: presence and status_updates 27720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 27730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 27740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2775cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 277681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 277781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 2778cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 2779cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 2780cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2781cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2782cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2783cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2784cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 2785cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2786cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 27874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2788de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2789de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 2790bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2791b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2792b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2793b5a4add17815167d20a90645779df34cdf45280dFred Quintana 279435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 279500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 279600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 2797b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 2798b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 2799b5a4add17815167d20a90645779df34cdf45280dFred Quintana Object data = values.get(ContactsContract.SyncStateColumns.DATA); 2800b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 2801b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 2802b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2803b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2804f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2805f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 280600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 280735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2808b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2809b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 2810b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2811b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 2812b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 2813b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2814b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2815b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2816b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2817b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 2818b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 281935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2820d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 28218c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 282200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 282300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 282400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2825d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 28268c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 2827c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2828c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2829c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 28302e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 28312e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 28322e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 28332e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 28342e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 28352e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 28362e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 28372e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 28382e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 28398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 28402e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 28412e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 28422e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 28437d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 28447d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 28457d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 28467d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 28477d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 28487d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 28497d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 28507d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 28517d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 28527d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 285320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2854944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2855f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 285681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2857f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 285881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 285920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 286020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2861c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 286248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 286348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 286448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 286548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2866f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 286781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2868f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 286981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 287000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 287100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 28727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 28735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 28745ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 28754529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 28767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 28777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 28787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 28795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 288033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 28814529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 28824529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=" + rawContactId 28834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 28844529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 28854529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContact(rawContactId, values); 28864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 28877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 28887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 28897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2890ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 28915aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 2892f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 289381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2894f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 289581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2896ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2897ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2898ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2899ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2900ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 290173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String selectionWithId = (Groups._ID + "=" + groupId + " ") 290273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 29035aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 29045aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 290581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2906f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 290781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2908ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2909ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2910ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2911127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 2912de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 2913b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2914b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2915b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2916eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 29175aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateSettings(uri, values, selection, selectionArgs); 291843880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2919eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2920eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2921eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 292281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 292381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2924f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 292581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 292600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 292700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 292800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 29294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 29304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 29315aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 2932f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 293373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 293473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 2935f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 293673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 293773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 293873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 293973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 294073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 294173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 294273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 294373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2944ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 29451a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 29461a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 294794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 29486ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 29496ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 29506ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi final long groupId = ContentUris.parseId(uri); 29516ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 29526ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Groups.ACCOUNT_TYPE}, Groups._ID + "=" + groupId, null, null, 29536ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 29546ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 29556ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 29566ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 29576ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 29586ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 29596ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 29606ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 29616ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 29626ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 29636ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 29646ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 29656ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 29666ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 29676ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 29686ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 29696ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 29706ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 297194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 297294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 297394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2974b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 2975b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 2976e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 29771a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 29781a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2979e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2980e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2981e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2982e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 29834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 29844529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 29854529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 29864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 29874529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 298873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 29894529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 2990b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 299151bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 29924529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 29934529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 29944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 29954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 29964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 29974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 29984529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 29994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 30004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 30014529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 30024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 30034529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 30044529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 30054529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 30064529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 300719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final String selection = RawContacts._ID + " = " + rawContactId; 300819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 300919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 301019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 301119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 301219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 301319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka null, null, null, null); 301419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 301519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 301619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 301719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 301819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 301919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 302019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 302119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 302219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 302319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 302419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int count = mDb.update(Tables.RAW_CONTACTS, values, selection, null); 30255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3026433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 30274529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3028433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3029285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 3030285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateLookupKey(mDb, rawContactId); 3031285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 303219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 303319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 303419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka mInsertedRawContacts.add(rawContactId); 303519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 30365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 303833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 303933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3040321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3041f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 304220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 304320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 304420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 30455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 304620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 304720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 304820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 304920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 305020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3051b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 305220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 305320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 305470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 305570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 305620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 305720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 305820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 305970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 306020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 306170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 306220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 306370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 306420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 306570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 306620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 306720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3068653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 306920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3070653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3071653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 307214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 3073653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 3074653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 3075f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 307620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3077653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 3078653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 307920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 308020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3081653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 308220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 308320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3084f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 3085653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 3086653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 3087321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3088653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 308914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 3090a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3091f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana rowHandler.update(mDb, values, c, callerIsSyncAdapter); 30928e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 3093a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 3094a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 3095a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 30968e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 3097653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 3098321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3099321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 31008c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 31018c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 31028c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 3103b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 31048c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 31058c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 31068c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 31078c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 31088c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 31098c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 31108c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 31118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 31128c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 31138c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 31148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 31158c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31168c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 31178c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 31188c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31198c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 3120d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 31218c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3122b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3123d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3124b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 3125d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3126b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 3127d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3128b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3129d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3130b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3131d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 3132d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3133d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 31348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 3135d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 3136d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3137d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 31388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 3139c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 31408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3141c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 3142c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 31438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=" + contactId, null); 31448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 31468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 31478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3148b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 31498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3150b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 31518c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3152b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 31538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3154b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 31558c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3156b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 31578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 31588c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31598c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=" + contactId, null); 3160f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3161d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3162ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton public void updateContactLastContactedTime(long contactId, long lastTimeContacted) { 3163ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 3164ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.bindLong(2, contactId); 3165ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.execute(); 3166d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3167d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3168127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 3169127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 31700c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 31710c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 317280c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 31730c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 31740c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 31750c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 31760c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 31770c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 31780c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 31790c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 3180b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3181127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 31820c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 31830c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 31840c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=" + rawContactId1 + " AND " 31850c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=" + rawContactId2, null); 31860c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 31876bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 31886bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 31890c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 31900c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 31910c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 31920c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 3193127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 3194127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3195dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 3196dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 3197dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 3198b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 31990c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 32000c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 3201b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId2 = mDbHelper.getContactId(rawContactId2); 32020c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 3203127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3204127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 3205127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 3206127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3207b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3208b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 320970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 3210b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 321170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (mDb == null) return; 321270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 321370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong Set<Account> validAccounts = Sets.newHashSet(); 321470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accounts) { 321570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong validAccounts.add(new Account(account.name, account.type)); 321670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 321770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong ArrayList<Account> accountsToDelete = new ArrayList<Account>(); 321870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 321970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 322070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 322148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 32225f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana for (String table : new String[]{Tables.RAW_CONTACTS, Tables.GROUPS, Tables.SETTINGS}) { 32235f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // Find all the accounts the contacts DB knows about, mark the ones that aren't 32245f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // in the valid set for deletion. 32255f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Cursor c = mDb.rawQuery("SELECT DISTINCT account_name, account_type from " 32265f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + table, null); 32275f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana while (c.moveToNext()) { 32285f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (c.getString(0) != null && c.getString(1) != null) { 32295f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Account currAccount = new Account(c.getString(0), c.getString(1)); 32305f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (!validAccounts.contains(currAccount)) { 32315f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana accountsToDelete.add(currAccount); 32325f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana } 323370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 323470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 32355f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana c.close(); 323670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 323770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 323870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 32395f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 324070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong String[] params = new String[]{account.name, account.type}; 324170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.GROUPS 324270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 324370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.PRESENCE 324470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (SELECT " 324570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS 324670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?)", params); 324770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.RAW_CONTACTS 324870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 32495f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana mDb.execSQL("DELETE FROM " + Tables.SETTINGS 32505f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + " WHERE account_name = ? AND account_type = ?", params); 325170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3252b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 325370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 325470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 325570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 325670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 325770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3258619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3259619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3260622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 3261622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 326267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 326367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 326467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 326567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 326667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 326767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 326867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 326967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 327067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 327167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 327267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 327367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 3274dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 3275622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 3276dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 3277dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 3278622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3279622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3280dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 3281622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3282622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 32834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 32844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 32854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 3286bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3287bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3288bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 32890b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 3290b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 329135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3292d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 32931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3294c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3295c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3296619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3297619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3298a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 32994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 330035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3301b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 330235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 330335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3304d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3305763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3306619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3307619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3308619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3309d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 33104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3311763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 33124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + contactId); 33136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 33146bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 33156bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 33165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 33175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 33185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 33195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 33205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 33215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 33225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 33245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 33255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 33265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3327763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 33285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=" + contactId + " AND " + 33295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.LOOKUP_KEY + "="); 33305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhereEscapeString(lookupKey); 33315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, selectionArgs, sortOrder, 33325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 33335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 33345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 33355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 33375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 33385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3340763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 33415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 33425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 33435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3345f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 3346f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 3347f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 3348763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 3349f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 3350f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 3351f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 3352f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 3353f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 3354ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3355763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3356ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 33574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 33584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3359e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 33605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 33614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sb.toString()); 3362ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3363ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3364ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3365ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3366ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3367ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 33684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3369ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3370d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 33714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 33724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3373e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 33745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 33754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 33764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 33774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3378763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3379ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 33804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 33814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 33824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3383d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3384d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final String starredQuery = qb.buildQuery(projection, Contacts.STARRED + "=1", 33854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3386d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3387d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3388d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3389763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 33904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 33914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3392d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3393d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String frequentQuery = qb.buildQuery(projection, 3394d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3395d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 33964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3397d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3398d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3399d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3400d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 34014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 34024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3403d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3404d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3405d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3406d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3407d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3408d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3409ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3410763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3411b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 341271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 34134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3414b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3415b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3416b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3417b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3418d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 34194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 342082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 34214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 34226bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 34236bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 342400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3425ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 34263653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 342782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 34283653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 34293653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 34303653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 34313653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 34323653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 34334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 343482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 343589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 34362815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 34372815f58f72f109790585931f601a63ddc02536a5Evan Millar } 34382815f58f72f109790585931f601a63ddc02536a5Evan Millar 343948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 344082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 344148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 344248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 344348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 344448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 344548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3446ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 344782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 344889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3449ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 34504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 34514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 34525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 34535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 34545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 34555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 34565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 34575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 345820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null, false); 34595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 34605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 34615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 34625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 34635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 34645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 34655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 34665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 34675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 34685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 34695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 34705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 34715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 34725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 34735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 34745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 34755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 34764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + sb); 3477ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 34785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3479a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3480a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3481a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 3482ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3483ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3484ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 34854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 348682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 348789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 34884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 34894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 34904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 349148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 349282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 349348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 349448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 349548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 349648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 349748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 34985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 349982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 350089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 35014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 35025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + Email.DATA + "="); 35034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhereEscapeString(uri.getLastPathSegment()); 35044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3505ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3506ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3507ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 35085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 350982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 351089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 35115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 35125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 35135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 35145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 35155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 351620938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 351720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 351820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 351920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 352020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null, false); 352120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(" OR "); 352220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 35235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 35255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Email.DATA + " LIKE "); 35261e530df9f7e496dc47f77d4323c89bd413b79b64Dmitri Plotnikov sb.append(DatabaseUtils.sqlEscapeString(filterParam + '%')); 35275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 35285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + sb); 35295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 3531a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3532a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3533a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 35345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 35355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3537ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 353882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 353989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 354089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3541ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3542ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3543ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 354448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 354582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 354648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 354748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 354848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 354948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 355048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 355148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 35525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 3553763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 35544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 35554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 35585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 3559763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 356089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 35614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 35624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 35655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 356682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 356789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=" + rawContactId); 3568e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3569e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3570e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 3571e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 357282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3573e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3574e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3575e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 35764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 357782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 357882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + ContentUris.parseId(uri)); 3579a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3580a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3581a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3582a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 35834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3584a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 3585a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 3586a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 3587e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 3588a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3589a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3590e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 3591b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 3592e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 3593e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 3594e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 3595e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 3596e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 3597a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3598a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3599a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3600ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 3601b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3602ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 360389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3604ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3605ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3606ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3607ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3608ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 3609b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3610ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 361189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(Groups._ID + "=" + groupId); 3612ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3613ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3614ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3615ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 3616b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 3617ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 361889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 361989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 3620ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3621ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3622ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3623b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 36240c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 3625b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 3626b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3627b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3628b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 362931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 3630d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 36312d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 36322d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 36332d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 36342d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 363531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 3636d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 3637d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 363831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 363931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 364031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 364131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3642763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 36437581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 36447581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 36452d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 364631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 364731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3648eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3649eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 3650eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 365189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3652e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3653e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 3654e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 3655b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 3656e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 365782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3658b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3659e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3660e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 366182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3662b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3663e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3664e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3665e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3666eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3667eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3668eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 366982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 36700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 36715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 36725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 36735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 367482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 36750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 36760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=" + ContentUris.parseId(uri)); 36775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 36785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 36795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 3680c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 3681a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 3682c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3683c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3684c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 3685b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3686b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh(db, contactId, projection); 3687c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3688c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 36891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 3690b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 36911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 36921b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 36931b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 36941b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 3695b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 36961b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 36971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 36981b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 36991b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37001b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 3701b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37021b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 37031b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 37041b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37051b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37061b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 3707b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37081b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 370971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 37101b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 37111b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37121b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 371346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 371446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 371546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 371646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 371746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 371846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 371946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 372046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 372146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 372246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 372346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 372446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 37254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 3726f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 3727c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 37284f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 37305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 37315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 37345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 37355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 3736038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 3737038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 3738038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 3739038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 37405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 37415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 37424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 37434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 37444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 37464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 37485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 37495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 37505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 37515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 37535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 37545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 37555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 37585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 37615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 37625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 37645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 37655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 37665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 37675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 37685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 37695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 37715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 37725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 37735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 37745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 37775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 37785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 37795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 37805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 37815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 37825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 37835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 37875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 37885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 37915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 37925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 37935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 37945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 37955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 37965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 37975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 37985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 38015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 38025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 38045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 38055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 38065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 38075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 38085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 38095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 38105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 38115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 38125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 38155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 38165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 38175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 38185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 38225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 38235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 38265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 38295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 38305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 38325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 38335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 38345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 38355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 38365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 38375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 38395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 38405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 38415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 38425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 38455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 38465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 38475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 38505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 38515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 38555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 38565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 38595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 38605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 38615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 38645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 38655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 38665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 38695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 38705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 38715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 38735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 38745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 38755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 38765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 38775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 38785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 38795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 38805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 38815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 38845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 38855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 38865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 38875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 38915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 38925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 38955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 38985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 38995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 39005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 39015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 39025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 39045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 39055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 39075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 39085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 39105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 39115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 39135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 39145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 39155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 39165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 39175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 39185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 39195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 39215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 39225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 39265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 39275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 39285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 39295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3932763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 3933763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 393482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 3935763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 3936763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 3937763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 3938763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 3939d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 3940763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 3941763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 3942b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 394382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 394482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 394582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 394682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 3947b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 394882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 394982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 395082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 395182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 395282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 39533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 39543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 3955a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 39563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 395782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 395882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 395982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 396082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 3961ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 3962763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 3963763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 3964763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 3965763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 3966763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 3967763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 3968d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 3969763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 3970763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 3971763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 3972763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 3973763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 3974763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 3975763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 397646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 397746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana // Note: currently, "export only" equals to "restricted", but may not in the future. 397846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana boolean excludeRestrictedData = readBooleanQueryParameter(uri, 397946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.FOR_EXPORT_ONLY, false); 398046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 398146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String requestingPackage = uri.getQueryParameter( 398246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 398346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana if (requestingPackage != null) { 398446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana excludeRestrictedData = excludeRestrictedData 398546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 398646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 398746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 398846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setProjectionMap(sRawContactsEntityProjectionMap); 398946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 399046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 399146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 399282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 399382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 399482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 3995d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa // Note: currently, "export only" equals to "restricted", but may not in the future. 3996763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = readBooleanQueryParameter(uri, 3997d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa Data.FOR_EXPORT_ONLY, false); 3998763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 3999763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 4000763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4001763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4002763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar excludeRestrictedData = excludeRestrictedData 4003d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4004763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4005763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4006763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getDataView(excludeRestrictedData)); 400782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 400882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 40093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated presence when requested 4010b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 401182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 40123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 401382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 401482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 401582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 40163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated status updates when requested 4017b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 401882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 401982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 402082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 402182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 402282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 40233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 40243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 402582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 40263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 4027ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 40283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 40293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual presence when requested 40303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 40313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 40323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdates.DATA_ID + "=" 40333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 40343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 40353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 40363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual status updates when requested 40373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, 40383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS, 40393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_RES_PACKAGE, 40403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_ICON, 40413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_LABEL, 40423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_TIMESTAMP)) { 40433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 40443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 40453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 40463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 40473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 404882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 404982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 405082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 4051ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 4052ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 40530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 40540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 40550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4056b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 40570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 40580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4059b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 40600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 40610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 40620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 40630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 40640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4065b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 40660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 40670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 40680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 40690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 40700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 40710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 40720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 40730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 40740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 40750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setTables(sb.toString()); 40760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 40770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 40780a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 40794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 40804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 40814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 40824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 40834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 40844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 40854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 40864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 40874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 40884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 40894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 40904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 40914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4092e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 4093e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 4094e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 4095e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(accountName)) { 4096e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 4097e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4098e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 4099e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 4100e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 4101e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 4102e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 4103e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 4104e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4105e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 4106e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 4107e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 4108e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4109e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4110e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 41117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 4112c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 4113c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 4114c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 4115c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 4116c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 4117c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private String getLimit(Uri url) { 4118c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limitParam = url.getQueryParameter("limit"); 4119c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 4120c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4121c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4122c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 4123c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 4124c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 4125c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 4126c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4127c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4128c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4129c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 4130c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 4131c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4132c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4133c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4134c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4135c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 41365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 41375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 41385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 41395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 41405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 41415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 41425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 41435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 41445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 41455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 41465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 41475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 41485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 41505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 41515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 41525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 41545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 41555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 41575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 41585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 41605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 41615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 41635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 41645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 41655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 416600ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 4167d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 416870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 416970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 41706cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 417170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 417270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 417370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 417470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 4175d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 417670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 417767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 41785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 41795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 4180619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4181619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4182619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4183b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 4184b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 4185b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 4186b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 4187d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 4188b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 4189b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 4190b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4191b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4192b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 4193b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4194b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 4195b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 4196b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 4197b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=" + contactId; 4198b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4199b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, null); 4200d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4201d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4202f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 4203d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 4204d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 420514b8a1243ab5c043b35e47527ca1c962064f3771Daisuke Miyakawa final String selection = Contacts._ID + "=" + contactId; 4206d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4207d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 4208d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 4209d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 4210d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 4211d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey outputRawContactsAsVCard(localStream, selection, null); 4212d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 4213d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4214b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4215b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 4216b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("No file at: " + uri); 4217b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4218b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4219b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4220d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 4221d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String VCARD_TYPE_DEFAULT = "default"; 4222d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4223d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4224d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 4225d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 4226d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4227d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 4228d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 4229d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 4230d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 4231d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4232d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 4233d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 4234d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4235d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 4236d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 4237d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 4238b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4239d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 4240d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 4241d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 4242d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4243d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 4244d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4245d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4246d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4247d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 4248d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 4249d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 4250d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4251d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 4252d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 4253d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 4254d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final VCardComposer composer = new VCardComposer(context, VCARD_TYPE_DEFAULT, false); 4255d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 4256d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4257f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 4258d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.init(selection, selectionArgs)) 4259d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 4260d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4261d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 4262d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 4263d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 4264d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4265d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4266d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 4267d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4268b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4269bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4270bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov private static Account readAccountFromQueryParams(Uri uri) { 4271bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String name = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 4272bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String type = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 4273bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 4274bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return null; 4275bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 4276bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return new Account(name, type); 4277bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 4278bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4279bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4280619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 42817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 42827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 42837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 4284d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static class RawContactsEntityIterator implements EntityIterator { 42857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 42867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 42877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 42887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 42897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 42907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 42917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 42927a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 42937a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 42947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 42957a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 42967a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 42977a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 42987a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 42997a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 43007a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 43017a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 43027a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 43037a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 43047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 43057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 43067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 43077a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4}; 43087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 430946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana public static final String[] PROJECTION = new String[]{ 43106cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 43116cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 43126cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.SOURCE_ID, 43136cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.VERSION, 43146cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.DIRTY, 431546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana RawContacts.Entity.DATA_ID, 43167a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RES_PACKAGE, 43177a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.MIMETYPE, 43187a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 43197a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 43207a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 43217a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 43227a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 43237a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 43247a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 43257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 43267a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 43277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 43287a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 43297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 43307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 43317a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 43327a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 43337a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 43347a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 43357a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 43367a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4, 433746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana RawContacts._ID, 43387a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.IS_PRIMARY, 43393cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar Data.IS_SUPER_PRIMARY, 43407a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA_VERSION, 43417a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana GroupMembership.GROUP_SOURCE_ID, 43427a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC1, 43437a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC2, 43447a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC3, 434594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana RawContacts.SYNC4, 434638446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey RawContacts.DELETED, 4347c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.CONTACT_ID, 4348c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.STARRED}; 4349035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 4350035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 4351035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 4352035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 4353035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 4354035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 4355035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 435667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_RES_PACKAGE = 6; 435767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_MIMETYPE = 7; 435867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA1 = 8; 43597a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_RAW_CONTACT_ID = 27; 43607a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_IS_PRIMARY = 28; 43613cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_IS_SUPER_PRIMARY = 29; 43623cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DATA_VERSION = 30; 43633cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_GROUP_SOURCE_ID = 31; 43643cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC1 = 32; 43653cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC2 = 33; 43663cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC3 = 34; 43673cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC4 = 35; 43683cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DELETED = 36; 43693cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_CONTACT_ID = 37; 43703cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_STARRED = 38; 43717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 437246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana public RawContactsEntityIterator(ContactsProvider2 provider, Uri entityUri, 437346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String contactsIdString, 437446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String selection, String[] selectionArgs, String sortOrder) { 43757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 437646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Uri uri; 43777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 437846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = Uri.withAppendedPath(RawContacts.CONTENT_URI, contactsIdString); 437946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = Uri.withAppendedPath(uri, RawContacts.Entity.CONTENT_DIRECTORY); 438046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } else { 438146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = ContactsContract.RawContactsEntity.CONTENT_URI; 4382035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 438346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana final Uri.Builder builder = uri.buildUpon(); 438446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String query = entityUri.getQuery(); 438546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana builder.encodedQuery(query); 438646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana mEntityCursor = provider.query(builder.build(), 438746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana PROJECTION, selection, selectionArgs, sortOrder); 43887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 43897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 43907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4391038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4392038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4393038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4394038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4395038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4396038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4397038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana 43987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 43997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 44007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 44017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 44037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 44047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 44077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 44087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 44097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 44127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 44157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 44167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 44177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 44197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 44207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 44237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44247a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final long rawContactId = c.getLong(COLUMN_RAW_CONTACT_ID); 44257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 44277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 44286cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 44296cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 44305ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 44316cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 44326cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 44336cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 44347a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC1, c.getString(COLUMN_SYNC1)); 44357a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC2, c.getString(COLUMN_SYNC2)); 44367a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC3, c.getString(COLUMN_SYNC3)); 44377a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC4, c.getString(COLUMN_SYNC4)); 443894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana contactValues.put(RawContacts.DELETED, c.getLong(COLUMN_DELETED)); 443938446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey contactValues.put(RawContacts.CONTACT_ID, c.getLong(COLUMN_CONTACT_ID)); 4440c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey contactValues.put(RawContacts.STARRED, c.getLong(COLUMN_STARRED)); 44417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 44427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 44447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 44457a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana if (rawContactId != c.getLong(COLUMN_RAW_CONTACT_ID)) { 44467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 44477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 444823c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// if (c.isNull(COLUMN_CONTACT_ID)) { 444923c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// continue; 445023c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// } 44517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 44527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 445323c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data._ID, c.getLong(COLUMN_DATA_ID)); 44547a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 44557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 445623c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_PRIMARY, c.getLong(COLUMN_IS_PRIMARY)); 445723c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_SUPER_PRIMARY, c.getLong(COLUMN_IS_SUPER_PRIMARY)); 44587a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 44599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 44609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana dataValues.put(GroupMembership.GROUP_SOURCE_ID, 44619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.getString(COLUMN_GROUP_SOURCE_ID)); 44629261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 44637a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 44647a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana for (int i = 0; i < DATA_KEYS.length; i++) { 44657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 44667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 44677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 44687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 44697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 44707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 44717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 44727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 44737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 44747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 44757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 44767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 44777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 44807e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 44817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 44837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4486226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana /** 4487226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 4488226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 4489226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana */ 4490226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static class GroupsEntityIterator implements EntityIterator { 4491226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private final Cursor mEntityCursor; 4492226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private volatile boolean mIsClosed; 4493226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4494226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final String[] PROJECTION = new String[]{ 4495226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups._ID, 4496226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_NAME, 4497226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_TYPE, 4498226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.SOURCE_ID, 4499226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.DIRTY, 4500226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.VERSION, 4501226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.RES_PACKAGE, 4502226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE, 4503226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE_RES, 45047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.GROUP_VISIBLE, 45057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC1, 45067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC2, 45077a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC3, 45087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC4, 45097a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYSTEM_ID, 451094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.NOTES, 45111a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey Groups.DELETED, 45121a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey Groups.SHOULD_SYNC}; 4513226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4514226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ID = 0; 4515226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_NAME = 1; 4516226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_TYPE = 2; 4517226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_SOURCE_ID = 3; 4518226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_DIRTY = 4; 4519226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_VERSION = 5; 4520226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_RES_PACKAGE = 6; 4521226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE = 7; 4522226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE_RES = 8; 4523226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_GROUP_VISIBLE = 9; 45247a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 10; 45257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 11; 45267a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 12; 45277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 13; 45287a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYSTEM_ID = 14; 45297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_NOTES = 15; 453094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana private static final int COLUMN_DELETED = 16; 45311a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private static final int COLUMN_SHOULD_SYNC = 17; 4532226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4533226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 4534226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 4535226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = false; 4536226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4537226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String updatedSortOrder = (sortOrder == null) 4538226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ? Groups._ID 4539226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana : (Groups._ID + "," + sortOrder); 4540226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4541b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = provider.mDbHelper.getReadableDatabase(); 4542226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 4543b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(provider.mDbHelper.getGroupView()); 4544226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setProjectionMap(sGroupsProjectionMap); 4545226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (groupIdString != null) { 4546226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups._ID + "=" + groupIdString); 4547226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4548226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountName = uri.getQueryParameter(Groups.ACCOUNT_NAME); 4549226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountType = uri.getQueryParameter(Groups.ACCOUNT_TYPE); 4550226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!TextUtils.isEmpty(accountName)) { 4551226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups.ACCOUNT_NAME + "=" 4552226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4553226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + Groups.ACCOUNT_TYPE + "=" 4554226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 4555226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4556226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 4557226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana null, null, updatedSortOrder); 4558226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToFirst(); 4559226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4560226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4561226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public void close() { 4562226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4563226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("closing when already closed"); 4564226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4565226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = true; 4566226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.close(); 4567226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4568226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4569226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public boolean hasNext() throws RemoteException { 4570226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4571226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 4572226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4573226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4574226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return !mEntityCursor.isAfterLast(); 4575226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4576226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4577038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4578038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4579038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4580038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4581038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4582038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4583e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4584226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public Entity next() throws RemoteException { 4585226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4586226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 4587226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4588226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!hasNext()) { 4589226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 4590226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4591226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4592226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 4593226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4594226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final long groupId = c.getLong(COLUMN_ID); 4595226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4596226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana // we expect the cursor is already at the row we need to read from 4597226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ContentValues groupValues = new ContentValues(); 4598226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 4599226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 4600226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups._ID, groupId); 4601226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 4602226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 4603226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 4604226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 4605226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 4606226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 4607226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 46087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC1, c.getString(COLUMN_SYNC1)); 46097a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC2, c.getString(COLUMN_SYNC2)); 46107a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC3, c.getString(COLUMN_SYNC3)); 46117a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC4, c.getString(COLUMN_SYNC4)); 46127a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYSTEM_ID, c.getString(COLUMN_SYSTEM_ID)); 461394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana groupValues.put(Groups.DELETED, c.getLong(COLUMN_DELETED)); 46147a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.NOTES, c.getString(COLUMN_NOTES)); 46151a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey groupValues.put(Groups.SHOULD_SYNC, c.getString(COLUMN_SHOULD_SYNC)); 4616226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Entity group = new Entity(groupValues); 4617226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4618226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToNext(); 4619226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4620226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return group; 4621226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4622226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4623226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4624a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 46257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 46267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 4627568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 4628568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 46297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 46307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 46315ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: 46325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: 46337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 46345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (match == RAW_CONTACTS_ID) { 46357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 46367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 46377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 463846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana return new RawContactsEntityIterator(this, uri, contactsIdString, 463946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana selection, selectionArgs, sortOrder); 4640226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS: 4641226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS_ID: 4642226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String idString = null; 4643226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (match == GROUPS_ID) { 4644226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana idString = uri.getPathSegments().get(1); 4645226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4646226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4647226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return new GroupsEntityIterator(this, idString, 4648226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana uri, selection, selectionArgs, sortOrder); 46497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 46507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 46517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 46527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 46537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 46544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 46554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4656a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 46574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4658b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4659b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP: 4660be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 4661b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4662b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4663b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4664f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 4665f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 4666b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4667be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4668b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4669b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4670508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4671b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 467248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 467348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 467448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 467548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 467648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 467748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 467848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 467948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 468048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 468148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 468248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 468348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4684b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4685b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4686b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4687b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4688b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4689b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4690b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4691b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4692c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4693c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4694c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4695c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 469661efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 469761efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 46984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 46994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 470125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private void setDisplayName(long rawContactId, String displayName, int bestDisplayNameSource) { 47023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 470325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindString(1, displayName); 47043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 470525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindNull(1); 47063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 470725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(2, bestDisplayNameSource); 470825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(3, rawContactId); 470925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 47103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 47113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 471273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 471373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 471473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 471573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 471673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.bindLong(1, rawContactId); 471773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.execute(); 471873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 471973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4720c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4721c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 4722c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 4723c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4724c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4725c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4726653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 4727c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 4728653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 4729653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 4730c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 4731c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4732c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 4733c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4734c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 4735c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 4736c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4737c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4738c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4739653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 4740c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 4741653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 4742653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 4743c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 4744c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4745ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4746f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 4747f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 4748f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4749f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4750f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4751f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); 4752f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (tokens.length == 0) { 4753f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4754f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4755f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4756f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String address = tokens[0].getAddress(); 4757f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int at = address.indexOf('@'); 4758f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (at != -1) { 4759f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov address = address.substring(0, at); 4760f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4761f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4762f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4763f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 4764f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4765f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4766f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4767f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 4768f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4769f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 4770f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 4771f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4772f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4773f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4774f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4775f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 4776f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4777f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4778a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 4779a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 4780a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 4781a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4782a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 4783a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4784a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 4785a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4786a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 4787a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4788a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4789f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4790f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name) { 4791f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name); 4792f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4793f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4794f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4795f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Returns nickname cluster IDs or null. Maintains cache. 4796f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4797f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4798f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SoftReference<String[]> ref; 4799f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4800f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4801f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (mNicknameClusterCache.containsKey(normalizedName)) { 4802f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = mNicknameClusterCache.get(normalizedName); 4803f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (ref == null) { 4804f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return null; 4805f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4806f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = ref.get(); 4807f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4808f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4809f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4810f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (clusters == null) { 4811f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = loadNicknameClusters(normalizedName); 4812f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = clusters == null ? null : new SoftReference<String[]>(clusters); 4813f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4814f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNicknameClusterCache.put(normalizedName, ref); 4815f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4816f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4817f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4818f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4819f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4820f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] loadNicknameClusters(String normalizedName) { 4821b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4822f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4823f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupQuery.TABLE, NicknameLookupQuery.COLUMNS, 4824f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.NAME + "=?", new String[] { normalizedName }, 4825f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov null, null, null); 4826f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov try { 4827f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int count = cursor.getCount(); 4828f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (count > 0) { 4829f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = new String[count]; 4830f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov for (int i = 0; i < count; i++) { 4831f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.moveToNext(); 4832f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters[i] = cursor.getString(NicknameLookupQuery.CLUSTER); 4833f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4834f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4835f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } finally { 4836f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.close(); 4837f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4838f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4839f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4840f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4841f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 4842f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4843f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 4844f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 4845f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4846f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4847f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4848f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 4849f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 4850f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 4851f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4852f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4853f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4854f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4855f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return ContactsProvider2.this.getCommonNicknameClusters(normalizedName); 4856f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4857f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4858f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4859f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4860f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 4861f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4862f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 4863f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 1, rawContactId); 4864f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 2, dataId); 4865f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 3, lookupType); 4866f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 4, name); 4867f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 4868f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4869f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4870f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4871f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 4872f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4873f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 4874f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupDelete, 1, dataId); 4875f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 4876f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4877f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 48782d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 4879d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4880d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 4881d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4882d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 4883d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 4884d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 4885d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 4886e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 4887d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN(" 4888d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 4889d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 4890d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NICKNAME + "," 4891d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.ORGANIZATION + "))"); 4892e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 4893e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 48945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 4895c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4896c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 4897c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 4898c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4899c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4900a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 4901c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit) { 490220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), limit, 490320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov true); 49045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 49055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 49065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 490720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String limit, boolean allowEmailMatch) { 4908d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4909d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + NameLookupColumns.RAW_CONTACT_ID + 4910d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 4911d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 4912d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 49135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 4914a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 4915a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 4916a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 491720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov + NameLookupType.ORGANIZATION); 491820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 491920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 492020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 492120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(")"); 49223de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 4923c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limit != null) { 4924c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(" LIMIT ").append(limit); 4925c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4926c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(")"); 4927ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4928ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 49294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 49304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 49314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 49324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 4933b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 4934b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 4935b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 4936b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 4937b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 49384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 49394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 4940b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 4941b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4942b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4943caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 4944caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 4945caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 4946caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 4947df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 4948df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 4949caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 4950caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 4951caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 4952caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 49536f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 4954caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 49556f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 4956caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 49574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 4958