ContactsProvider2.java revision a8d8b1cb48a6e94645dbce836193b40c7481356c
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; 111315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikovimport java.util.BitSet; 1125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 113b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1140e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 116622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 117b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1180e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 119ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1255b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 126caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 127bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 128bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 129bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 131619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 132619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 133619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1450e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1460e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 147a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 149d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 150d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.TIMES_CONTACTED + " DESC, " 1519b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 152d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 154d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 155d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 156d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 157d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 166f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 1674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 17146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 1724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1736bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1746bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 175ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 17648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 17748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 17848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 17948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 18048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 18148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 18248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 18348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 184a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1856bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1866bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 187b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 188b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 189b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 19082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 19182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 1921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 19331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 19431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 195eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 196eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 197ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 198ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 199ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 200ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 20135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 202b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 20335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 204c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 205c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 206c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2071b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2081b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2091b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2101b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2111b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 21246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 21346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 214d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 215f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 216f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 217f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 21867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 21967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2206cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 222f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 223ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 224ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 225d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 22667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 227d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 228ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 23014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 23167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 23388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 238f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 23988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 24088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 24188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 24288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 24388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 24488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 24588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 246f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 24914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 253f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 2543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 25614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 257321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 25820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 25920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 260321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 261321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 26220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 26320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 264f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 26519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 26619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 26719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 26819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 269ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 270ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 271ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 27219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 27319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 27419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 275ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 276ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 27719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 27819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 27925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private static final HashMap<String, Integer> sDisplayNameSources; 2803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov static { 28125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources = new HashMap<String, Integer>(); 28225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(StructuredName.CONTENT_ITEM_TYPE, 28325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.STRUCTURED_NAME); 284a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sDisplayNameSources.put(Nickname.CONTENT_ITEM_TYPE, 285a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka DisplayNameSources.NICKNAME); 28625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Organization.CONTENT_ITEM_TYPE, 28725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.ORGANIZATION); 28825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Phone.CONTENT_ITEM_TYPE, 28925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.PHONE); 29025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Email.CONTENT_ITEM_TYPE, 29125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.EMAIL); 2923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 29331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 294c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 295df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 296caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 29771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 29871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 29971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 30071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 30171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 30271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 30371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 30471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 30571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 30671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 30771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 30871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 30971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 31071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 311a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 312a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 313a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 314a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 315a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 316a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 317a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 318a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 319a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 320a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 321a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 322a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 323038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 324038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 325e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 327f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 328f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final HashMap<String, String> sContactsVCardProjectionMap; 329ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 330d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 33146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** Contains the columns from the raw contacts entity view*/ 33246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final HashMap<String, String> sRawContactsEntityProjectionMap; 3334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3379261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 338e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 339ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 340ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 341ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 342ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 343373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 344b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 345eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 346eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 34782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 34882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 3491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 3539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 3549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 3559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 3569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 3579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 358c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 359c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 361c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 362ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton /** Precompiled sql statement for incrementing times contacted for a contact */ 363ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton private SQLiteStatement mContactsLastTimeContactedUpdate; 3643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 36525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 36682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 367a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 368f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 369f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 370a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 371a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 372a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 3730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 374a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 375a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 376f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 377f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 378f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 379f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 3814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 382a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 383d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 384d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 385d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 3863653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 3873653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 3882d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 3892d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 3903653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 3915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 3925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 3935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 394f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 3955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 396ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 397ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 3985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 3993653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 40346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 40446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 40546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 406b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 409ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 41048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 412ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 41448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 418ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 41948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 421ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 422ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 423ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 424ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 42535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 426b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 427b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 42835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 429a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 430b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 431b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 432b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 433b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 435eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 436eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 43782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 43882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 4391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 440c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 441c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 442c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 443c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 444c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 445c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 446c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4471b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4481b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 4511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 4521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 4531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 4541b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 45519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 45619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 45719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 458038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 459038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 460e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 4624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 4634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 4644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 470f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 4714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 473f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 4743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 4753296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 4763296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 4773296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 4783296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 4793296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 4803296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 4813296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 4823296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 4833296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 4843296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 4853296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 4863296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 4873296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 488f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap = Maps.newHashMap(); 489f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 490d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 491f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "0 AS " + OpenableColumns.SIZE); 4924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 4944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 4954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 4964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 4974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 4984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 4994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 5014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 5024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 5034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 5044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 5054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 5064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 5074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 5084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 5094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 5104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 5114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 5124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 5132815f58f72f109790585931f601a63ddc02536a5Evan Millar 5144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 5154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 5164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 5174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 5234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 5244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 5254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 5264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 5274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 5284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 5294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 5304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 5314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 5324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 5334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 5344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 5354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 5364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 5374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 54182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 5424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 54756d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 555a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 5564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 557a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 55846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana HashMap<String, String> columns; 55946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns = new HashMap<String, String>(); 56046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts._ID, RawContacts._ID); 56146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 56246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 56346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 56446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 56546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.VERSION, RawContacts.VERSION); 56646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 56746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DELETED, RawContacts.DELETED); 56846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 56946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 57046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 57146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 57246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 57346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.MIMETYPE, Data.MIMETYPE); 57446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA1, Data.DATA1); 57546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA2, Data.DATA2); 57646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA3, Data.DATA3); 57746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA4, Data.DATA4); 57846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA5, Data.DATA5); 57946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA6, Data.DATA6); 58046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA7, Data.DATA7); 58146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA8, Data.DATA8); 58246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA9, Data.DATA9); 58346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA10, Data.DATA10); 58446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA11, Data.DATA11); 58546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA12, Data.DATA12); 58646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA13, Data.DATA13); 58746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA14, Data.DATA14); 58846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA15, Data.DATA15); 58946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC1, Data.SYNC1); 59046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC2, Data.SYNC2); 59146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC3, Data.SYNC3); 59246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC4, Data.SYNC4); 59346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 59446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.STARRED, Data.STARRED); 59546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 59646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 59746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 59846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 59946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana sRawContactsEntityProjectionMap = columns; 60046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 6013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 6023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 6033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 6043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 6053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 6063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 6073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 6113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 6133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 6143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 6163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.PRESENCE, 6173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 6183296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS, 6193296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 6203296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 6213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 6233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_LABEL, 6253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_ICON, 6273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 6283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 6305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 6315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 6325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 6335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 6345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 6355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 6365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 6375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 6385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 6395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 6405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 6415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 6425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 6435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 6445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 6455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 6465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 6475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 6485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 6495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 6505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 6515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 6525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 6535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 6545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 6555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 6565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 6575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 6588f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 6595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 6605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 6615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 6625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 6635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 6645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 6655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 666a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 6675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 6685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 6695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 6703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 6713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 6723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 6733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 6743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 6753296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 6763296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6773296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6783296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6793296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 6803296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6813296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 6823296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 6833296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6843296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 6853296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 6863296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 6873296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS, 6883296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 6893296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 6903296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6913296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 6923296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6933296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 6943296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6953296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 6963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 6973296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 698e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 699e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 700e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_ID + " AS " + PhoneLookup._ID); 70156d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 70256d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar Contacts.LOOKUP_KEY + " AS " + PhoneLookup.LOOKUP_KEY); 703e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 704e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + PhoneLookup.DISPLAY_NAME); 705e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 706e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 707e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 708e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 709e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " + PhoneLookup.TIMES_CONTACTED); 710e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 711e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_STARRED + " AS " + PhoneLookup.STARRED); 712e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 713e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 714e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 715e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.PHOTO_ID + " AS " + PhoneLookup.PHOTO_ID); 716e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 717e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " + PhoneLookup.CUSTOM_RINGTONE); 718e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 719e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.HAS_PHONE_NUMBER + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 720e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 721e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 722e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 723e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 724e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 725e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 726e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 727e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 728e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 7299261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 730ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 731ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 73289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 733035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 734035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 7359261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 7369261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 7379261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 73889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 739ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 74067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 741ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 7423cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 74394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 7443cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 74538446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 74689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 74789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 74889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 74989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 750ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 751ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 7526cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 753ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 754ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 755d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 756d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 757ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 758ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 759ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 760d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 761d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 762ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 763f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 764ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 765ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 766b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 767b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 768b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 769b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 7700c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 7710c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 772b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 773b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 774eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 775eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 776eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 777eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 778eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 779eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 780341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 781341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 782341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 783fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 784341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 785341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 786341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 78768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 78868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 78968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 79068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 79168936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 792e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 79368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 79468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 79568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 796eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 797eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 798373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 7994dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 8000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 8010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 80282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 80382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 80482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 80570c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 80670c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 80782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 80882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 80982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 81082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 8110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 8120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 8130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 8140a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 8150a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 81682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 81719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 8181b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 8191b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 8201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 8211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 8221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 8231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 8241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 8251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 8261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 8271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 8281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 8294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 8304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 8313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 8323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey map.put(toField, fromField + " AS " + toField); 8333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 8343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 8353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 8373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 8393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 841653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 8423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 8443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 845a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 846a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 847a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 848a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 849a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 850a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 851a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 852a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 8533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 855653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 856653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 857b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 858653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 859653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 860653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 861653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 8623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 8643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 866e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 867e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 868e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 869e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 870653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 871e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 872e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 873e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 8743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 8783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 8793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 880653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 881f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 88214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 88314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 884653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 885653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 886653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 887653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 888653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 889653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 890653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 891653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 892653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 893653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 894653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 895653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 896653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 897653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 898653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 899653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 900653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 901653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " = " + dataId, null); 902653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 903653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 904f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 905653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 906653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 9073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 91014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 91114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 91214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 9133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 9143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 9153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 9165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 9173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 9193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 9225ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long newPrimaryId = findNewPrimaryDataId(db, rawContactId); 9233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (newPrimaryId != -1) { 92414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov setIsPrimary(rawContactId, newPrimaryId, getMimeTypeId()); 9253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9285ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected long findNewPrimaryDataId(SQLiteDatabase db, long rawContactId) { 929e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 930e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 9315ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Cursor c = queryData(db, rawContactId); 9323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 933e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 93414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 935f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 936e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 937e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 938e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 939e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 9403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 9423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 9433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 944e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return primaryId; 945e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 946e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 947e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 948e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 949e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 950e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 951e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 952e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 9533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected Cursor queryData(SQLiteDatabase db, long rawContactId) { 95614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return db.query(DataDeleteQuery.TABLE, DataDeleteQuery.CONCRETE_COLUMNS, 95714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId + 95814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " AND " + MimetypesColumns.MIMETYPE + "='" + mMimetype + "'", 9593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov null, null, null, null); 9603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 96225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 963285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 964d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(db, rawContactId); 965285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateDisplayName(db, rawContactId); 966285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 9673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 968a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 969a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 970a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return true; 971a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 972622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 973622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 974622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 975622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * as baseline, but augmented with any updates. 976622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 977622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 978622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 979622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 980622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=" + dataId, 981622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey null, null, null, null); 982622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 983622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 984622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 985622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 986622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.put(key, cursor.getString(i)); 987622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 988622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 989622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 990622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 991622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 992622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 993622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 994622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 9953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 9983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 10003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1005622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 10063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1007622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 10083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1009622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 10103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 10135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1014622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 101514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 101614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 101714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1018f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1019f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 102025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 102114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 102214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 102314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 102414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 102514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1026f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1027622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1028622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1029cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1030622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1031622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 103214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1033f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 103414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1035f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 1036f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1037f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1038f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 103914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 104025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 104114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 104214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 104314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 104414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 104514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 104614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 104714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 104814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 104914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1050f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 105125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 105214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 10533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1056622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 10573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1058622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1060622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1061622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 10623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1063622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1064622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1065622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1066622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1067622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1068622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1069622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 107067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1071622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 107267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 107367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1074622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1075622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 10768c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1077622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1078622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 107967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 108067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 108167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 108267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 108367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 108467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 10858c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1086622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 1087622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(name); 1088622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 1089622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1090622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1091622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1092622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1093622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1094622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1095622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1096622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1097622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1098622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1099622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1100622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1101622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1102622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1103622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1104622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1105622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1106622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1107622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1108622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1109f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1110622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1111622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1112622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1113f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1114622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1115622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1116622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1117622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1118622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1119622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1120622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1121622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1122622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1123622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1124622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1125622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1126622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1127622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1128622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1129622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1130622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1131622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 113267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 113367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 113467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 113567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1136622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1137622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1138622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1139622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1140622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1141622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 114267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 114367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 114467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1145622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1146622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1147622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 11483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 11533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 11553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 11563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 11583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 11593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 11603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 11613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1165622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1166622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1167622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1169622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1170622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1171f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1172622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1173622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1174622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1175f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1176622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1178622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1179622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1180622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1181622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1182622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1183622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1184622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1185622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 11863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1187622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1188622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1189622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1190622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1191622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 11963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 11983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 11993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1203a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1204a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1205a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1206a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1207a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 120825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1209a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1210a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 12113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 121414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1215f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1216a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1217a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1218a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 121914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 122014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1221f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 122214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 122325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1224a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 1225a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 122614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 122714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 122814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 122914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1230a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 123114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 123214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 123314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 123425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1235a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 123614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 123714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 123814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 123914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 12403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 12413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 12423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 12433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 12443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 12453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 12463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1248a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1249a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1250a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1251a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1252a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 12533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1255e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1256e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1257e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1258e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1259e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1260e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1261e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 12625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 126314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 126414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 126514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 126614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 126725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1268f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 126914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 127014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 127114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 127214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 127314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1274f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 127514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 127614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 127714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 127814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1279f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 128014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1281f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1282f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 128325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 128414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 128514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 128614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 128714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 128814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 128914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 129014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 129214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1293f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 129425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 129514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1296e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1297e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1298e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1299e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1300e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1301e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1302e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1303e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1304e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1305e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1306e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1307e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1308e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1309e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 131014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 131114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 131214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 131314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 131414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 131514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 131614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 131714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 131814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 131914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 132014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 132114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 132225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1323f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 132414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 132514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 132614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 132714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 132814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1329f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 133014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 133114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 133214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 133314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1334f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 133514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1336f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1337f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 133825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 133914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 134014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 134114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 134214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 134314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 134414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 134514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 134614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 134714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1348f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 134925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 135014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 135114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 135214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 135314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 13543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 13553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 13573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 13583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 13620b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 13630b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 13640b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 13650b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1366653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 13670b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1368653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 13690b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1370285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 137125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 13720b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 13730b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 13740b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1375653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1376653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1377653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1378653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1379653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1380f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 138114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 138214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 13830b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 13840b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 13850b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1386653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1387f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1388653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 13890b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1390285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 139125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 13920b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 1393f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 13940b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 139514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 139614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 139714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 139814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 139914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 140014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 140114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 140214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 140314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 140414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1405285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 140625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 140714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1408653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1409653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1410653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1411e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1412e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1413e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1414e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1415653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1416653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1417653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1418e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1419653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1420653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1421e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1422653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 14235ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1424653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1425e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 142636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.MIN_MATCH, 142736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov PhoneNumberUtils.toCallerIDMinMatch(number)); 142836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov 1429653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1430653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1431653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=" + dataId, null); 1432e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 14333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 14363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 14373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 14383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 14393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 14403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 14413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 14423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 14433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 14443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 14453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 14463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 14473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1451653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1452653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1453653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1454653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1455653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1456653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1457653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1458653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1459653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 14600be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 14610be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 14620be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1463653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1464653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1465653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1466653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1467f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 146814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1469653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1470f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 14710be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 14720be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 14730be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 14740be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 14750be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 14760be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 14770be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 14780be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 14790be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 14800be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 14810be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 14820be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1483b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 14840be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1485b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 14860be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1487653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1488653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1489653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1490653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1491653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1492653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1493653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1494653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1495653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1496653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1497653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1498653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1499653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1500653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1501653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1502653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1503653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1504653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1505653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1506653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1507653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1508653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1509653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1510653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1511ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId, 1512ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.get(rawContactId)); 1513653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1514653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1515653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1516653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1517a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1518a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1519a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1520a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1521a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1522653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1523653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1524a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1525a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1526a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1527a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1528a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1529a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1530a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1531a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1532a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1533285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1534285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1535285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1536a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1537a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1538a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1539a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1540a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1541f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1542a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1543f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1544a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1545a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1546a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1547a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1548a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1549a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1550a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1551a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1552a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1553a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1554a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1555a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1556a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1557a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1558a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1559a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1560a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1561ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov /** 1562ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 1563ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1564ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1565ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov public class GroupIdCacheEntry { 1566ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1567ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 1568ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1569ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1570ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1571a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 15723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 157353056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 1574b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 157531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 15764097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1577f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1578315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1579315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov // We will use this much memory (in bits) to optimize the nickname cluster lookup 1580315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private static final int NICKNAME_BLOOM_FILTER_SIZE = 0x1FFF; // =long[128] 1581315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private BitSet mNicknameBloomFilter; 1582315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1583ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, SoftReference<String[]>> mNicknameClusterCache = Maps.newHashMap(); 1584ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 1585622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1586622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1587ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1588ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1589ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // is a list of groups with this group id. 1590ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1591ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 1592622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1593f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1594a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1595a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 159620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 159720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1598ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 159973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1600ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<Long, Account> mInsertedRawContacts = Maps.newHashMap(); 1601b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1602a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private HashSet<Long> mDirtyRawContacts = Sets.newHashSet(); 1603b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1604de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 16051a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 16061a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 160781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 160881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 1609a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 161053056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 1611a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1612a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1613a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1614a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 1615a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 161653056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 161753056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 1618a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 16194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 16204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 16214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1622de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 162335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1624de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1625b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1626a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1627b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1628b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper, mAggregationScheduler); 16290e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1630a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1631b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 1632653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1633c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1634653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1635653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1636653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1637653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1638653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1639c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1640653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1641653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1642653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1643653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1644653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1645653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1646653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1647653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1648653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1649653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1650653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1651ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate = db.compileStatement( 1652ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton "UPDATE " + Tables.CONTACTS + 1653ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton " SET " + Contacts.LAST_TIME_CONTACTED + "=? " + 1654ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton "WHERE " + Contacts._ID + "=?"); 1655a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 165625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate = db.compileStatement( 165725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 165825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " SET " + RawContactsColumns.DISPLAY_NAME + "=?," 165925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov + RawContactsColumns.DISPLAY_NAME_SOURCE + "=?" + 166025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 16613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1662a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate = db.compileStatement( 1663a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.CONTACTS + 1664a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1665a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1666a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1667a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1668a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1669a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1670a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1671a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1672a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1673a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 16740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 16750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1676a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " LIMIT 1)" + 1677a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1678e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1679622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Locale locale = Locale.getDefault(); 168028f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 168128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 168228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 168328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 1684622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey context.getString(com.android.internal.R.string.common_name_conjunctions), 1685622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey locale); 1686f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 1687622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mPostalSplitter = new PostalSplitter(locale); 16884097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1689f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1690f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1691f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1692f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1693f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1694f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1695f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1696a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert = db.compileStatement( 1697a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1698a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 16990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 1704a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1705a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace = db.compileStatement( 1706a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1707a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 17090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1714a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1715a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp = db.compileStatement( 1716a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 17180a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 1719a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 17200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 17210a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 17220a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate = db.compileStatement( 17230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 17250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 17260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 17270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1728a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1729a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete = db.compileStatement( 1730a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1731a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1732a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 17333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 17343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1735e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 17363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 17373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 173867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 173967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 17403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 17413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 174214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 17433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 17443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1745622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1746622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1747a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1748a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 17493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 17503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1751568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 17523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1753568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1754c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov verifyAccounts(); 175570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 1756f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1757f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 1758315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov preloadNicknameBloomFilter(); 17591f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 17604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 17614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1762c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 1763c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1764c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1765c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 1766c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 176731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1768de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1769b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1770b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 177131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 177231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1773285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov /* package */ ContactAggregationScheduler getContactAggregationScheduler() { 1774285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mAggregationScheduler; 1775285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1776285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1777013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1778013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1779013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1780013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 17813d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 17823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 17833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 17843d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 17853d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1786568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1787568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1788568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1789568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1790568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1791568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1792568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1793568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1794568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1795ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1796568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1797568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1798568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1799568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1800568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1801568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1802568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1803568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1804568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1805568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1806ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1807ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1808568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov scheduleContactAggregation(); 1809568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1810568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1811568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1812568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1813568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1814568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1815568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 18163d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1817568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1818568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 18193d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18203d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 18213d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 18223d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 18233d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 18243d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 18253d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 18263d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18273d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18283d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 18293d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1830568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 18310e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 18323d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 18333d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 18343d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 18350e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(aggregatorEnabled); 18363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 18373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 18383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 18393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 18403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1843a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1844a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 1845a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 1846a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 1847a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1848a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1849a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 1850a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1851a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1852a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1853a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1854a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1855a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1856b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 1857a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1858a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1859568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1860568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 1861568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1862568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1863568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1864568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1865568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1866568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 1867ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 1868ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 1869ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 1870ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 1871ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 1872ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1873ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 1874ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 187581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 1876ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1877ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1878568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1879568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1880568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1881568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1882568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1883568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1884568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1885568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1886568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1887568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1888568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1889568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1890568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1891568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1892568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1893568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1894568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 1895568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1896568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1897568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1898568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1899568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1900568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1901568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 1902568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1903568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1904568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1905568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1907285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1908bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1909b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1910b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1911285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 19121ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1913b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1914b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1915b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1916b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 1917285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 1918b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 1919df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 1920a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.clear(); 1921285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1922285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1923285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1924285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 1925bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1926b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1927b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1928285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1929b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 19301ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 19311a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 19321a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 1933b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 19341a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 1935b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1936b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1937b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1938bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1939b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1940b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 194108e42c9c153a60bf2e7c71dd40bf84bb5fc93555Dmitri Plotnikov for (long rawContactId : mInsertedRawContacts.keySet()) { 1942d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(mDb, rawContactId); 1943d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mContactAggregator.onRawContactInsert(mDb, rawContactId); 1944285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1945b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1946a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov if (!mDirtyRawContacts.isEmpty()) { 1947a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 1948a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 1949a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mDirtyRawContacts); 1950a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 1951a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 1952a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 1953a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1954b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 1955a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 1956a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 1957a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mUpdatedRawContacts); 1958a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 1959a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 1960b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1961b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1962b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 1963b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 1964b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().update(mDb, id, entry.getValue()); 1965b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1966b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1967b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1968b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1969b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1970a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 1971a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 1972a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 1973a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 1974a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private void appendIds(StringBuilder sb, HashSet<Long> ids) { 1975b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 1976a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 1977b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1978a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1979a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 1980285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1981285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1982285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1983cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 198481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 198581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 198681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 198781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 198881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 198981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 199081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 1991cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 1992568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1993568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected void scheduleContactAggregation() { 1994dee54bb86f3608730f0b9f37d8982a7f6b280a85Dmitri Plotnikov mContactAggregator.schedule(); 1995568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1996568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1997285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 1998ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return mInsertedRawContacts.containsKey(rawContactId); 1999285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2000285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 20013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 20023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 20033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 20043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 20053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 20063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 20083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 20104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2011de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2012bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2013b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "insertInTransaction: " + uri); 2014b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2015f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2016f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2017f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2018f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2019a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2020a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 202135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2022a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 202335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2024b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 202535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 202635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2027d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2028d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 20296bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 20306bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 20316bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 20325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2033f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 2034d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov id = insertRawContact(values, account); 2035f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2036a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2037a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2038a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 20395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 20405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2041f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2042f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2043a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2044a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2045a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2046a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2047f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2048f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2049a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2050a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2051a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2052ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2053ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 20545aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertGroup(uri, values, account, callerIsSyncAdapter); 2055f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2056ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2057ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2058ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2059eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 20605aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 206143880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2062eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2063eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2064eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 206582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 206682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 20671f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 20681f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20691f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2070a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 207181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2072f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2073a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2074a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 20757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 20767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 20777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 20787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2079de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2080a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2081a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2082a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2083035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 2084035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 2085035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 2086035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 2087035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 20887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2089035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 2090035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 20916cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME); 20926cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2093035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 2094035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 2095035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 2096035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 2097035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2098035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 2099035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2100035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 2101df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_NAME, account.name); 2102df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_TYPE, account.type); 2103035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2104035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 21057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 21077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2108d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 21096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 21106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 21116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 21126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2113d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2114de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 21156bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 21166bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 21176bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2118a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2119a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2120a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2121f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 2122a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2123a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2124d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertRawContact(ContentValues values, Account account) { 2125a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 2126d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov overriddenValues.putNull(RawContacts.CONTACT_ID); 2127f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 21287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 21297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 21313d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 21323d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 21333d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov overriddenValues.put(RawContacts.AGGREGATION_MODE, 21343d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DISABLED); 21353d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 21363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2137023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov long rawContactId = 2138023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, overriddenValues); 2139023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 2140285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2141285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2142ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.put(rawContactId, account); 2143023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2144a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2145a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2146a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2147a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2148a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2149a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2150a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2151a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2152f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2153a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2154de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2155de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 215667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2157de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 215820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2159de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2160de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2161de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2162b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2163de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2164de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2165508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2166de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2167de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2168de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2169de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2170de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 21714097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2172b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2173de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2174a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2175a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2176a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2177f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2178de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2179a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2180b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2181a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2182a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2183a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2184a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2185a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 21864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 21874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 21888e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 21898e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 21908e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 21918e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 21928e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2193b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2194f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 21958e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 21968e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 21978e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 21988e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2199421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 2200f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22018e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 22028e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 22038e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2204b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2205f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 22068e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 22078e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 22088e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2209f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22108e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2211f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2212c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 2213b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 22148e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2215f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22168e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2217f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2218f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2219f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2220a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 22215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 22229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 22239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 22245ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 22259261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 22269261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 22279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 22289261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 22299261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 2230ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId, 2231ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Account account) { 2232ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2233ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (account == null) { 2234ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 2235ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts._ID + "=" + rawContactId, null, null, null, null); 2236ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov try { 2237ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2238ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = c.getString(RawContactsQuery.ACCOUNT_NAME); 2239ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = c.getString(RawContactsQuery.ACCOUNT_TYPE); 2240ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 2241ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov account = new Account(accountName, accountType); 2242ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 22439261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2244ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } finally { 2245ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov c.close(); 22469261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22479261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2248ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 22499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 22509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 2251ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov + "has a sourceid the the contact must be associated with " 22529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 22539261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22549261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2255ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ArrayList<GroupIdCacheEntry> entries = mGroupIdCache.get(sourceId); 2256ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entries == null) { 2257ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries = new ArrayList<GroupIdCacheEntry>(1); 2258ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.put(sourceId, entries); 2259ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2260ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2261ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int count = entries.size(); 2262ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov for (int i = 0; i < count; i++) { 2263ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = entries.get(i); 2264ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entry.accountName.equals(account.name) && entry.accountType.equals(account.type)) { 2265ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 2266ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2267ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2268ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2269ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = new GroupIdCacheEntry(); 2270ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountName = account.name; 2271ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountType = account.type; 2272ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.sourceId = sourceId; 2273ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries.add(0, entry); 2274ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 22759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 22765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 2277ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 22789261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2279df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 22809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 2281ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2282ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = c.getLong(0); 22839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 22849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2285df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2286df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 22879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 22889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 22899261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 22909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 22919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 22929261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2293ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = groupId; 22949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 22969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 22979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2298ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2299ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 23009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2302d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private interface DisplayNameQuery { 2303d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2304d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2305d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 2306d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov MimetypesColumns.MIMETYPE, 2307d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov Data.IS_PRIMARY, 2308d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov Data.DATA1, 2309d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov Organization.TITLE, 2310d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov }; 2311d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2312d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int MIMETYPE = 0; 2313d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int IS_PRIMARY = 1; 2314d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int DATA = 2; 2315d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int TITLE = 3; 2316d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2317d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2318d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov /** 2319d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * Updates a raw contact display name based on data rows, e.g. structured name, 2320d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * organization, email etc. 2321d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov */ 2322d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 2323d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov String bestDisplayName = null; 2324d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 2325d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2326d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov Cursor c = db.query(DisplayNameQuery.TABLE, DisplayNameQuery.COLUMNS, 2327d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId, null, null, null, null); 2328d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov try { 2329d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov while (c.moveToNext()) { 2330d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov String mimeType = c.getString(DisplayNameQuery.MIMETYPE); 2331d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2332d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov // Display name is at DATA1 in all type. This is ensured in the constructor. 2333d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov String name = c.getString(DisplayNameQuery.DATA); 2334d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov if (TextUtils.isEmpty(name) 2335d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov && Organization.CONTENT_ITEM_TYPE.equals(mimeType)) { 2336d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov name = c.getString(DisplayNameQuery.TITLE); 2337d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2338d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov boolean primary = StructuredName.CONTENT_ITEM_TYPE.equals(mimeType) 2339d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov || (c.getInt(DisplayNameQuery.IS_PRIMARY) != 0); 2340d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2341d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov if (name != null) { 2342d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov Integer source = sDisplayNameSources.get(mimeType); 2343d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov if (source != null 2344d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov && (source > bestDisplayNameSource 2345d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov || (source == bestDisplayNameSource && primary))) { 2346d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov bestDisplayNameSource = source; 2347d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov bestDisplayName = name; 2348d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2349d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2350d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2351d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2352d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } finally { 2353d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov c.close(); 2354d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2355d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2356d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov setDisplayName(rawContactId, bestDisplayName, bestDisplayNameSource); 2357d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2358d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 23599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 236020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 236120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2362f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 236320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 236420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2365de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2366de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 236714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2368de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2369de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 237014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 237114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2372a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2373a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2374f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 237588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 2376a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2377a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2378a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 237988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 238020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 238120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2382de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 238320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 238420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 238520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 238620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 238720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 238888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 238988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 239088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 239120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2392f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 239388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 239488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 239514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=" + dataId, null, 239614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov null); 2397f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 239820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 239920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 240020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 240120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 240220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 240314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 240420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 240520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 240620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 240720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 240820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 240920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 241020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 241120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 241220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 24137a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 241420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 241520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 241620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2417a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2418a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 24198e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2420a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2421a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2422a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 24238e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 242420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 242520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 242620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 242720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 242820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 242920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2430ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2431ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2432b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, Account account, 2433b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov boolean callerIsSyncAdapter) { 2434ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 2435ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 2436ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 2437ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2438ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2439ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 244067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.RES_PACKAGE); 244167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 2442b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov overriddenValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 244367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 244467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.remove(Groups.RES_PACKAGE); 2445ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2446f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 244773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov overriddenValues.put(Groups.DIRTY, 1); 244873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 244973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2450ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey long result = mDb.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 2451ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 24521a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (overriddenValues.containsKey(Groups.GROUP_VISIBLE)) { 24531a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2454ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2455ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2456ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2457ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2458ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 24595aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2460e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 24615aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 24621a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 24631a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2464e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 24651a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 2466e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2467e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2468e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2469ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 247082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 24711f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 247282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 247382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 24740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 24754dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 24764dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 24770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 247882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 24794dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 24804dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 24814dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 24824dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 24831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2485dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 2486dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 248782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 2488f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 2489dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 2490dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 2491dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2492f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "="); 2493f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(dataId); 24941f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 2495dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 2496dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 24970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 24980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 24990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 25000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2501dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 2502dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 2503dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2504dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 2505f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2506f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 2507f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 2508f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 2509f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2510f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 2511f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 2512f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (") 2513f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2514f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(",") 2515f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2516f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(")" + " AND " + Data.DATA1 + "="); 2517f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2518f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ((" + DataColumns.MIMETYPE_ID + "=") 2519f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2520f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2521f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol); 2522dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2523f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2524f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2525dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2526f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=") 2527f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2528f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append("))"); 2529dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 2530f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=") 2531f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2532f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2533f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol) 2534f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.DATA + "="); 2535f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2536dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2537f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2538f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2539dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2540dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 25411f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 254282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 2543f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=") 254482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .append(values.getAsLong(StatusUpdates.DATA_ID)); 2545dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 254670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 2547f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 254870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 25491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 25501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2551de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 2552c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov mSb.toString(), null, null, null, 2553c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 25541f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 255567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 25565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2557e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 25581f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 25591f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 25601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 25611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25621f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 256331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 256431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 256531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 25661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25671f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 256882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2569a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2570a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2571a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2572a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2573a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2574a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2575a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 257682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2577a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2578a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 257982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 258082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 258182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 258282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 258382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2584a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 258582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 258682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 25871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2588a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2589a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2590a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2591e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 25920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 259382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 259482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 25950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 25960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 25970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 25980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 25990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 26000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 26010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 26020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 26030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 26040a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 26050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 26060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2607a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 2608a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 2609a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 261082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 261182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 2612a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 2613a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 26140a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 3, status); 26150a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 4, resPackage); 26160a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 5, iconResource); 26170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 6, labelResource); 2618a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 2619a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 2620a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2621a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 2622a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 26230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 2, status); 26240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 3, resPackage); 26250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 4, iconResource); 26260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 5, labelResource); 2627a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 2628a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 2629a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 26300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 2631a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 26320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 2, status); 2633a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 26340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 4, status); 2635a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 26360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 26370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 1, resPackage); 26380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 2, iconResource); 26390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 3, labelResource); 26400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 26410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 2642a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2643e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2644e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2645bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2646a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2647a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 2648a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 2649a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 2650a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2651a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2652a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 26531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 26541f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 26554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2656de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2657bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2658b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2659b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2660b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2661f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2662f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2663508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2664508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 266535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2666b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 266735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2668b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2669b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2670b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2671b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2672b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2673b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2674cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2675cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2676cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2677cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2678cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2679d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2680d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2681cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 26826bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 26836bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 26842e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 26852e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 26862e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 26872e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 26882e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 26892e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 26902e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26912e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 26922e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 26932e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 26942e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26952e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 26962971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 26972971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 26982971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2699e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 27002971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 27012971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 27022971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2703f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana numDeletes += deleteRawContact(rawContactId, callerIsSyncAdapter); 27042971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27052971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 27062971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 27072971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27082971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 27092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27102971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 27115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 27122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2713f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteRawContact(rawContactId, callerIsSyncAdapter); 2714508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2715508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 271620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2717f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2718944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2719f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 272020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 272120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 272248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 272348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 272448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 272548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2726508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2727f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2728f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteData(Data._ID + "=" + dataId, null, callerIsSyncAdapter); 2729ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2730ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2731ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2732f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 27335aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 27342971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27352971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 27362971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 27372971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 27382971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2739e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 27402971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 27412971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 27425aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 27432971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27442971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 27452971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 27462971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 274781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2748f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 274981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 27502971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2751508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2752508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2753eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 275443880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 27555aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteSettings(uri, selection, selectionArgs); 2756eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2757eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 275882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 27590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 27601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 27611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 276281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 276381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 27643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 276581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2766508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 27674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 276946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static boolean readBooleanQueryParameter(Uri uri, String name, boolean defaultValue) { 27702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final String flag = uri.getQueryParameter(name); 27712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return flag == null 27722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana ? defaultValue 27732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana : (!"false".equals(flag.toLowerCase()) && !"0".equals(flag.toLowerCase())); 277494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 277594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 27765aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 2777ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 2778b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 277994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2780de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 278194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 278294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 278394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 278494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2785f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2786de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 278794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 278894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 278994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2790f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2791de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 279294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 279394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 27941a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 279594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 279694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 279794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 27985aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2799e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 28001a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2801e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2802e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2803e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2804cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 2805cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2806cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null); 2807cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2808cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2809cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2810cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 2811cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2812cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2813cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2814cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2815cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2816cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2817cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2818cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2819f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana public int deleteRawContact(long rawContactId, boolean callerIsSyncAdapter) { 28203389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 2821f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 282214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2823de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 282433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2825b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 2826cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 282733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 282833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 282933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 28300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 28319705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 28329705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 28339705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 28349705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 28359705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 28369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 28379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 28389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 28390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 28400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2841cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 284281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 284381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 2844cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 2845cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 2846cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2847cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2848cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2849cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2850cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 2851cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2852cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 28534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2854de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2855de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 2856bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2857b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2858b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2859b5a4add17815167d20a90645779df34cdf45280dFred Quintana 286035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 286100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 286200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 2863b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 2864b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 2865b5a4add17815167d20a90645779df34cdf45280dFred Quintana Object data = values.get(ContactsContract.SyncStateColumns.DATA); 2866b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 2867b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 2868b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2869b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2870f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2871f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 287200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 287335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2874b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2875b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 2876b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2877b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 2878b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 2879b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2880b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2881b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2882b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2883b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 2884b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 288535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2886d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 28878c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 288800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 288900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 289000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2891d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 28928c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 2893c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2894c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2895c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 28962e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 28972e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 28982e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 28992e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 29002e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 29012e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 29022e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 29032e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 29042e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 29058c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 29062e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 29072e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 29082e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 29097d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 29107d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 29117d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 29127d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 29137d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 29147d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 29157d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 29167d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 29177d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 29187d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 291920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2920944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2921f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 292281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2923f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 292481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 292520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 292620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2927c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 292848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 292948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 293048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 293148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2932f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 293381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2934f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 293581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 293600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 293700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 29387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 29395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 29405ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 29414529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 29427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 29437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 29447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 29455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 294633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 29474529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 29484529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=" + rawContactId 29494529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 29504529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 295127f039b535f98c1cb1a31207047003235ddaed15Dmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=" + rawContactId, null); 29524529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 29537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 29547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 29557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2956ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 29575aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 2958f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 295981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2960f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 296181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2962ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2963ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2964ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2965ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2966ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 296773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String selectionWithId = (Groups._ID + "=" + groupId + " ") 296873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 29695aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 29705aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 297181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2972f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 297381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2974ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2975ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2976ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2977127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 2978de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 2979b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2980b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2981b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2982eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 29835aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateSettings(uri, values, selection, selectionArgs); 298443880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2985eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2986eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2987eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 29889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 29899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 29909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 29919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 29929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 299381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 299481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2995f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 299681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 299700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 299800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 299900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 30004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 30014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 30029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 30039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 30049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 30059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 30069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 30079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 30089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 30099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 30109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 30119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 30129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 30139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 30159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 30169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 30179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 30189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 30199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 30209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 30229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 30239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 30249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 30269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 30279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 30289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 30299705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 30309705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 30319705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 30329705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 30339705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 30349705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 30359705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 30379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 30389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 30399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 30409705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 30419705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 30429705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 30439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 30449705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 30459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 30469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 30479705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 30489705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 30499705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 30509705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30519705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 30529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 30539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 30549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 30559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 30569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 30579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 30589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 30595aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 3060f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 306173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3062ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3063ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 306473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 3065f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 306673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 306773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 306873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 306973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 307073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 307173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 307273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 307373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3074ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 30751a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 30761a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 307794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 30786ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 30796ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 30806ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi final long groupId = ContentUris.parseId(uri); 30816ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 30826ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Groups.ACCOUNT_TYPE}, Groups._ID + "=" + groupId, null, null, 30836ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 30846ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 30856ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 30866ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 30876ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 30886ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 30896ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 30906ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 30916ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 3092ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 30936ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 30946ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 30956ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 30966ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 30976ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 30986ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 30996ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 31006ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 310194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 310294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 310394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 3104b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 3105b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 3106e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 31071a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 31081a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3109e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3110e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3111e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3112e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 31134529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 31144529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 31154529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 31164529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 31174529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 311873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 31194529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3120b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 312151bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 31224529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 31234529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 31244529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 31254529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 31264529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 31274529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 31284529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 31294529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 31304529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 31314529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 31324529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 31334529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 31344529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 31354529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 31364529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 313719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final String selection = RawContacts._ID + " = " + rawContactId; 313819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 313919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 314019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 3141ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 3142ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 314319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 314419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 314519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka null, null, null, null); 314619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 314719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 314819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 3149ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 3150ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 315119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 315219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 315319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 315419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 315519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 315619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 315719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 315819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int count = mDb.update(Tables.RAW_CONTACTS, values, selection, null); 31595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3160433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 31614529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3162433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3163285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 3164285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateLookupKey(mDb, rawContactId); 3165285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 316619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 316719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 3168ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.put(rawContactId, new Account(accountName, accountType)); 316919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 31705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 317233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 317333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3174321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3175f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 317620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 317720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 317820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 31795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 318020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 318120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 318220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 318320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 318420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3185b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 318620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 318720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 318870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 318970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 319020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 319120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 319220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 319370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 319420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 319570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 319620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 319770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 319820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 319970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 320020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 320120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3202653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 320320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3204653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3205653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 320614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 3207653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 3208653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 3209f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 321020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3211653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 3212653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 321320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 321420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3215653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 321620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 321720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3218f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 3219653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 3220653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 3221321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3222653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 322314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 3224a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3225f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana rowHandler.update(mDb, values, c, callerIsSyncAdapter); 32268e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 3227a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 3228a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 3229a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 32308e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 3231653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 3232321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3233321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 32348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 32358c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 32368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 3237b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 32388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 32398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 32408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 32418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 32428c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 32438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 32448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 32458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 32468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 32478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 32488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 32498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 32508c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 32518c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 32528c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 32538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 3254d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 32558c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3256b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3257d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3258b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 3259d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3260b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 3261d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3262b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3263d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3264b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3265d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 3266d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3267d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 32688c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 3269d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 3270d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3271d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 32728c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 3273c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 32748c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3275c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 3276c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 32778c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=" + contactId, null); 32788c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 32798c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 32808c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 32818c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3282b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 32838c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3284b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 32858c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3286b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 32878c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3288b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 32898c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3290b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 32918c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 32928c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 32938c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=" + contactId, null); 3294f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3295d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3296ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton public void updateContactLastContactedTime(long contactId, long lastTimeContacted) { 3297ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 3298ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.bindLong(2, contactId); 3299ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.execute(); 3300d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3301d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3302127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 3303127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 33040c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 33050c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 330680c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 33070c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 33080c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 33090c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 33100c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 33110c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 33120c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 33130c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 3314b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3315127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 33160c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 33170c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 33180c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=" + rawContactId1 + " AND " 33190c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=" + rawContactId2, null); 33200c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 33216bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 33226bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 33230c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 33240c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 33250c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 33260c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 3327127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 3328127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 33293389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3330dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 3331dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 3332dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 3333b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 33340c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 33350c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 3336b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId2 = mDbHelper.getContactId(rawContactId2); 33370c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 3338127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3339127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 3340127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 3341127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3342b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3343b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 334470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 3345b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 334670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (mDb == null) return; 334770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 334870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong Set<Account> validAccounts = Sets.newHashSet(); 334970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accounts) { 335070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong validAccounts.add(new Account(account.name, account.type)); 335170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 335270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong ArrayList<Account> accountsToDelete = new ArrayList<Account>(); 335370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 335470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 335570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 335648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 33575f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana for (String table : new String[]{Tables.RAW_CONTACTS, Tables.GROUPS, Tables.SETTINGS}) { 33585f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // Find all the accounts the contacts DB knows about, mark the ones that aren't 33595f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // in the valid set for deletion. 33605f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Cursor c = mDb.rawQuery("SELECT DISTINCT account_name, account_type from " 33615f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + table, null); 33625f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana while (c.moveToNext()) { 33635f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (c.getString(0) != null && c.getString(1) != null) { 33645f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Account currAccount = new Account(c.getString(0), c.getString(1)); 33655f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (!validAccounts.contains(currAccount)) { 33665f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana accountsToDelete.add(currAccount); 33675f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana } 336870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 336970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 33705f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana c.close(); 337170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 337270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 337370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 33745f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 337570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong String[] params = new String[]{account.name, account.type}; 337670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.GROUPS 337770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 337870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.PRESENCE 337970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (SELECT " 338070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS 338170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?)", params); 338270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.RAW_CONTACTS 338370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 33845f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana mDb.execSQL("DELETE FROM " + Tables.SETTINGS 33855f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + " WHERE account_name = ? AND account_type = ?", params); 338670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3387b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 338870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 338970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 339070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 339170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 339270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3393619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3394619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3395622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 3396622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 339767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 339867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 339967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 340067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 340167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 340267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 340367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 340467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 340567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 340667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 340767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 340867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 3409dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 3410622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 3411dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 3412dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 3413622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3414622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3415dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 3416622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3417622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 34184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 34194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 34204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 3421bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3422bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3423bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 34240b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 3425b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 342635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3427d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 34281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3429c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3430c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3431619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3432619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3433a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 34344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 343535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3436b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 343735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 343835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3439d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3440763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3441619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3442619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3443619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3444d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 34454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3446763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 34474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + contactId); 34486bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 34496bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 34506bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 34515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 34525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 34535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 34545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 34555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 34565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 34575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 34595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 34605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 34615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3462763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 34635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=" + contactId + " AND " + 34645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.LOOKUP_KEY + "="); 34655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhereEscapeString(lookupKey); 34665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, selectionArgs, sortOrder, 34675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 34685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 34695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 34705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 34735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3475763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 34765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 34775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 34785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3480f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 3481f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 3482f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 3483763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 3484f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 3485f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 3486f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 3487f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 3488f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 3489ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3490763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3491ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 34924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 34934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3494e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 34955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 34964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sb.toString()); 3497ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3498ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3499ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3500ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3501ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3502ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 35034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3504ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3505d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 35064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 35074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3508e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 35095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 35104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 35114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 35124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3513763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3514ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 35154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 35164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 35174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3518d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3519d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final String starredQuery = qb.buildQuery(projection, Contacts.STARRED + "=1", 35204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3521d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3522d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3523d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3524763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 35254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 35264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3527d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3528d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String frequentQuery = qb.buildQuery(projection, 3529d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3530d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 35314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3532d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3533d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3534d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3535d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 35364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 35374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3538d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3539d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3540d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3541d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3542d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3543d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3544ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3545763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3546b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 354771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 35484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3549b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3550b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3551b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3552b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3553d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 35544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 355582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 35564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 35576bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 35586bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 355900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3560ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 35613653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 356282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 35633653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 35643653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 35653653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 35663653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 35673653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 35684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 356982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 357089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 35712815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 35722815f58f72f109790585931f601a63ddc02536a5Evan Millar } 35732815f58f72f109790585931f601a63ddc02536a5Evan Millar 357448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 357582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 357648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 357748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 357848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 357948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 358048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3581ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 358282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 358389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3584ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 35854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 35864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3587a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 35885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 35895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 35905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 35915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 35925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 359320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null, false); 35945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 35955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 35975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 35985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 35995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 36005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 36025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 36035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 36045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 36055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 36065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 36075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 36085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 36095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 3611a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 3612ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 36135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3614a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3615a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3616a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 3617ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3618ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3619ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 36204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 362182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 362289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 36234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 36244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 36254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 362648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 362782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 362848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 362948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 363048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 363148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 363248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 36335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 363482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 363589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 36364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 36375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + Email.DATA + "="); 36384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhereEscapeString(uri.getLastPathSegment()); 36394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3640ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3641ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3642ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 36435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 364482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 364589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 36465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 36475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 36485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3649a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 36505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 365120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 365220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 365320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 365420938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 365520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null, false); 365620938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(" OR "); 365720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 36585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 36605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Email.DATA + " LIKE "); 36611e530df9f7e496dc47f77d4323c89bd413b79b64Dmitri Plotnikov sb.append(DatabaseUtils.sqlEscapeString(filterParam + '%')); 36625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 3663a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 36645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 3666a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3667a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3668a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 36695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 36705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3672ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 367382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 367489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 367589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3676ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3677ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3678ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 367948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 368082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 368148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 368248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 368348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 368448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 368548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 368648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 36875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 3688763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 36894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 36904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 36935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 3694763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 369589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 36964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 36974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 37005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 370182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 370289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=" + rawContactId); 3703e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3704e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3705e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 3706e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 370782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3708e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3709e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3710e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 37114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 371282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 371382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + ContentUris.parseId(uri)); 3714a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3715a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3716a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3717a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 37184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3719a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 3720a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 3721a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 3722e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 3723a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3724a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3725e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 3726b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 3727e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 3728e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 3729e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 3730e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 3731e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 3732a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3733a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3734a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3735ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 3736b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3737ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 373889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3739ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3740ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3741ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3742ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3743ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 3744b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3745ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 374689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(Groups._ID + "=" + groupId); 3747ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3748ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3749ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3750ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 3751b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 3752ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 375389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 375489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 3755ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3756ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3757ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3758b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 37590c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 3760b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 3761b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3762b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3763b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 376431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 3765d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 37662d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 37672d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 37682d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 37692d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 377031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 3771d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 3772d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 377331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 377431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 377531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 377631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3777763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 37787581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 37797581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 37802d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 378131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 378231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3783eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3784eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 3785eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 378689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3787e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3788e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 3789e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 3790b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 3791e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 379282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3793b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3794e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3795e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 379682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3797b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3798e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3799e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3800e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3801eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3802eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3803eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 380482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 38050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 38065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 38075ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 38085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 380982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 38100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 38110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=" + ContentUris.parseId(uri)); 38125ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 38135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 38145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 3815c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 3816a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 3817c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3818c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3819c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 3820b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3821b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh(db, contactId, projection); 3822c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3823c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 38241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 3825b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 38261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 38271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 38281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 38291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 3830b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 38311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 38321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 38331b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 38341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 38351b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 3836b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 38371b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 38381b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 38391b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 38401b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 38411b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 3842b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 38431b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 384471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 38451b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 38461b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 38471b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 384846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 384946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 385046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 385146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 385246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 385346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 385446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 385546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 385646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 385746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 385846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 385946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 38604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 3861f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 3862c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 38634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 38644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 38655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 38665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 38695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 38705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 3871038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 3872038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 3873038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 3874038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 38755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 38765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 38774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 38784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 38794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 38804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 38814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 38824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 38835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 38845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 38855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 38865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 38885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 38895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 38905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 38935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 38965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 38975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 38995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 39005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 39015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 39025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 39035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 39045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 39065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 39075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 39085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 39095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 39125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 39135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 39145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 39155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 39175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 39185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 39225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 39235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 39265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 39275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 39285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 39295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 39315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 39325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 39335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 39365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 39375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 39395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 39405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 39415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 39425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 39435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 39445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 39455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 39465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 39475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 39485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 39505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 39515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 39525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 39535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 39575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 39585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 39615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 39645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 39655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 39675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 39685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 39695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 39705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 39715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 39725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 39745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 39755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 39765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 39775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 39805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 39815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 39825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 39835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 39855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 39865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 39905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 39915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 39945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 39955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 39965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 39975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 39995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 40005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 40015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 40045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 40055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 40065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 40085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 40095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 40105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 40115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 40125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 40135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 40145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 40155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 40165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 40175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 40185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 40195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 40205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 40215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 40225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 40265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 40275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 40305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 40335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 40345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 40355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 40365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 40375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 40395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 40405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 40425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 40435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 40455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 40465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 40475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 40485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 40495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 40505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 40515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 40525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 40535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 40545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 40565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 40575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 40615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 40625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 40635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 40645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4067763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 4068763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 406982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4070763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4071763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 4072763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4073763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4074d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4075763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4076763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 4077b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 407882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 407982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 408082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 408182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4082b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 408382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 408482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 408582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 408682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 408782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 40883296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 40893296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 4090a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 40913296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 409282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 409382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 409482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 409582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4096ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 4097763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 4098763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 4099763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4100763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 4101763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4102763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4103d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4104763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4105763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 4106763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 4107763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 4108763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 4109763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4110763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 411146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 411246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana // Note: currently, "export only" equals to "restricted", but may not in the future. 411346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana boolean excludeRestrictedData = readBooleanQueryParameter(uri, 411446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.FOR_EXPORT_ONLY, false); 411546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 411646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String requestingPackage = uri.getQueryParameter( 411746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 411846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana if (requestingPackage != null) { 411946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana excludeRestrictedData = excludeRestrictedData 412046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 412146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 412246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 412346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setProjectionMap(sRawContactsEntityProjectionMap); 412446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 412546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 412646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 412782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 412882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 412982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4130d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa // Note: currently, "export only" equals to "restricted", but may not in the future. 4131763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = readBooleanQueryParameter(uri, 4132d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa Data.FOR_EXPORT_ONLY, false); 4133763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4134763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 4135763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4136763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4137763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar excludeRestrictedData = excludeRestrictedData 4138d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4139763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4140763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4141763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getDataView(excludeRestrictedData)); 414282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 414382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 41443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated presence when requested 4145b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 414682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 41473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 414882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 414982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 415082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 41513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated status updates when requested 4152b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 415382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 415482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 415582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 415682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 415782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 41583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 41593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 416082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 41613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 4162ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 41633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 41643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual presence when requested 41653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 41663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 41673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdates.DATA_ID + "=" 41683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 41693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 41703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 41713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual status updates when requested 41723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, 41733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS, 41743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_RES_PACKAGE, 41753296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_ICON, 41763296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_LABEL, 41773296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_TIMESTAMP)) { 41783296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 41793296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 41803296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 41813296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 41823296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 418382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 418482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 418582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 4186ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 4187ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 41880a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 41890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 41900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4191b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 41920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 41930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4194b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 41950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 41960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 41970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 41980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 41990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4200b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 42010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 42020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 42030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 42040a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 42050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 42060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 42070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 42080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 42090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 42100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setTables(sb.toString()); 42110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 42120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 42130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 42144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 42154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 42164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 42174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 42184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 42194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 42204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 42214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 42224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 42234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 42244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 42254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 42264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4227e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 4228e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 4229e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 4230e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(accountName)) { 4231e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 4232e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4233e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 4234e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 4235e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 4236e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 4237e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 4238e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 4239e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4240e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 4241e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 4242e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 4243e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4244e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4245e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 42467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 4247c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 4248c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 4249c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 4250c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 4251c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 4252c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private String getLimit(Uri url) { 4253c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limitParam = url.getQueryParameter("limit"); 4254c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 4255c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4256c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4257c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 4258c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 4259c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 4260c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 4261c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4262c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4263c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4264c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 4265c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 4266c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4267c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4268c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4269c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4270c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 42715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 42725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 42735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 42745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 42755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 42765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 42775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 42785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 42795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 42805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 42815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 42825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 42835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 42855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 42865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 42875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 42895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 42905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 42925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 42935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 42955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 42965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 42985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 42995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 43005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 430100ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 4302d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 430370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 430470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 43056cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 430670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 430770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 430870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 430970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 4310d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 431170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 431267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 43135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 43145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 4315619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4316619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4317619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4318b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 4319b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 4320b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 4321b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 4322d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 4323b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 4324b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 4325b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4326b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4327b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 4328b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4329b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 4330b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 4331b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 4332b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=" + contactId; 4333b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4334b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, null); 4335d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4336d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4337f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 4338d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 4339d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 434014b8a1243ab5c043b35e47527ca1c962064f3771Daisuke Miyakawa final String selection = Contacts._ID + "=" + contactId; 4341d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4342d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 4343d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 4344d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 4345d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 4346d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey outputRawContactsAsVCard(localStream, selection, null); 4347d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 4348d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4349b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4350b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 4351b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("No file at: " + uri); 4352b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4353b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4354b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4355d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 4356d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String VCARD_TYPE_DEFAULT = "default"; 4357d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4358d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4359d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 4360d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 4361d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4362d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 4363d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 4364d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 4365d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 4366d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4367d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 4368d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 4369d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4370d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 4371d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 4372d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 4373b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4374d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 4375d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 4376d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 4377d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4378d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 4379d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4380d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4381d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4382d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 4383d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 4384d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 4385d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4386d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 4387d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 4388d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 4389d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final VCardComposer composer = new VCardComposer(context, VCARD_TYPE_DEFAULT, false); 4390d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 4391d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4392f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 4393d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.init(selection, selectionArgs)) 4394d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 4395d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4396d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 4397d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 4398d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 4399d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4400d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4401d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 4402d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4403b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4404bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4405bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov private static Account readAccountFromQueryParams(Uri uri) { 4406bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String name = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 4407bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String type = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 4408bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 4409bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return null; 4410bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 4411bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return new Account(name, type); 4412bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 4413bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4414bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4415619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 44167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 44177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 44187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 4419d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static class RawContactsEntityIterator implements EntityIterator { 44207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 44217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 44227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 44247a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 44257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 44267a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 44277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 44287a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 44297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 44307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 44317a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 44327a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 44337a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 44347a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 44357a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 44367a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 44377a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 44387a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 44397a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 44407a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 44417a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 44427a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4}; 44437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 444446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana public static final String[] PROJECTION = new String[]{ 44456cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 44466cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 44476cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.SOURCE_ID, 44486cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.VERSION, 44496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.DIRTY, 445046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana RawContacts.Entity.DATA_ID, 44517a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RES_PACKAGE, 44527a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.MIMETYPE, 44537a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 44547a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 44557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 44567a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 44577a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 44587a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 44597a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 44607a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 44617a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 44627a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 44637a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 44647a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 44657a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 44667a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 44677a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 44687a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 44697a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 44707a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 44717a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4, 447246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana RawContacts._ID, 44737a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.IS_PRIMARY, 44743cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar Data.IS_SUPER_PRIMARY, 44757a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA_VERSION, 44767a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana GroupMembership.GROUP_SOURCE_ID, 44777a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC1, 44787a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC2, 44797a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC3, 448094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana RawContacts.SYNC4, 448138446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey RawContacts.DELETED, 4482c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.CONTACT_ID, 4483c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.STARRED}; 4484035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 4485035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 4486035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 4487035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 4488035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 4489035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 4490035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 449167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_RES_PACKAGE = 6; 449267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_MIMETYPE = 7; 449367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA1 = 8; 44947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_RAW_CONTACT_ID = 27; 44957a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_IS_PRIMARY = 28; 44963cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_IS_SUPER_PRIMARY = 29; 44973cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DATA_VERSION = 30; 44983cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_GROUP_SOURCE_ID = 31; 44993cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC1 = 32; 45003cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC2 = 33; 45013cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC3 = 34; 45023cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC4 = 35; 45033cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DELETED = 36; 45043cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_CONTACT_ID = 37; 45053cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_STARRED = 38; 45067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 450746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana public RawContactsEntityIterator(ContactsProvider2 provider, Uri entityUri, 450846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String contactsIdString, 450946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String selection, String[] selectionArgs, String sortOrder) { 45107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 451146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Uri uri; 45127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 451346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = Uri.withAppendedPath(RawContacts.CONTENT_URI, contactsIdString); 451446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = Uri.withAppendedPath(uri, RawContacts.Entity.CONTENT_DIRECTORY); 451546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } else { 451646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = ContactsContract.RawContactsEntity.CONTENT_URI; 4517035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 451846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana final Uri.Builder builder = uri.buildUpon(); 451946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String query = entityUri.getQuery(); 452046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana builder.encodedQuery(query); 452146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana mEntityCursor = provider.query(builder.build(), 452246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana PROJECTION, selection, selectionArgs, sortOrder); 45237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 45247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4526038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4527038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4528038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4529038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4530038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4531038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4532038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana 45337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 45347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 45357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 45367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 45387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 45397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 45427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 45437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 45447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 45477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 45507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 45517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 45527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 45547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 45557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 45587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45597a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final long rawContactId = c.getLong(COLUMN_RAW_CONTACT_ID); 45607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 45627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 45636cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 45646cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 45655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 45666cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 45676cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 45686cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 45697a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC1, c.getString(COLUMN_SYNC1)); 45707a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC2, c.getString(COLUMN_SYNC2)); 45717a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC3, c.getString(COLUMN_SYNC3)); 45727a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC4, c.getString(COLUMN_SYNC4)); 457394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana contactValues.put(RawContacts.DELETED, c.getLong(COLUMN_DELETED)); 457438446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey contactValues.put(RawContacts.CONTACT_ID, c.getLong(COLUMN_CONTACT_ID)); 4575c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey contactValues.put(RawContacts.STARRED, c.getLong(COLUMN_STARRED)); 45767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 45777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 45797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 45807a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana if (rawContactId != c.getLong(COLUMN_RAW_CONTACT_ID)) { 45817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 45827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 458323c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// if (c.isNull(COLUMN_CONTACT_ID)) { 458423c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// continue; 458523c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// } 45867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 45877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 458823c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data._ID, c.getLong(COLUMN_DATA_ID)); 45897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 45907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 459123c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_PRIMARY, c.getLong(COLUMN_IS_PRIMARY)); 459223c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_SUPER_PRIMARY, c.getLong(COLUMN_IS_SUPER_PRIMARY)); 45937a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 45949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 45959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana dataValues.put(GroupMembership.GROUP_SOURCE_ID, 45969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.getString(COLUMN_GROUP_SOURCE_ID)); 45979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 45987a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 45997a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana for (int i = 0; i < DATA_KEYS.length; i++) { 46007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 46017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 46027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 46037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 46047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 46057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 46067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 46077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 46087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 46097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 46107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 46117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 46127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 46137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 46147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 46157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 46167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 46177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 46187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 46197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 46207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4621226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana /** 4622226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 4623226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 4624226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana */ 4625226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static class GroupsEntityIterator implements EntityIterator { 4626226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private final Cursor mEntityCursor; 4627226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private volatile boolean mIsClosed; 4628226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4629226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final String[] PROJECTION = new String[]{ 4630226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups._ID, 4631226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_NAME, 4632226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_TYPE, 4633226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.SOURCE_ID, 4634226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.DIRTY, 4635226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.VERSION, 4636226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.RES_PACKAGE, 4637226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE, 4638226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE_RES, 46397a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.GROUP_VISIBLE, 46407a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC1, 46417a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC2, 46427a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC3, 46437a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC4, 46447a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYSTEM_ID, 464594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.NOTES, 46461a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey Groups.DELETED, 46471a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey Groups.SHOULD_SYNC}; 4648226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4649226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ID = 0; 4650226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_NAME = 1; 4651226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_TYPE = 2; 4652226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_SOURCE_ID = 3; 4653226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_DIRTY = 4; 4654226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_VERSION = 5; 4655226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_RES_PACKAGE = 6; 4656226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE = 7; 4657226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE_RES = 8; 4658226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_GROUP_VISIBLE = 9; 46597a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 10; 46607a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 11; 46617a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 12; 46627a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 13; 46637a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYSTEM_ID = 14; 46647a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_NOTES = 15; 466594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana private static final int COLUMN_DELETED = 16; 46661a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private static final int COLUMN_SHOULD_SYNC = 17; 4667226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4668226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 4669226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 4670226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = false; 4671226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4672226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String updatedSortOrder = (sortOrder == null) 4673226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ? Groups._ID 4674226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana : (Groups._ID + "," + sortOrder); 4675226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4676b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = provider.mDbHelper.getReadableDatabase(); 4677226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 4678b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(provider.mDbHelper.getGroupView()); 4679226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setProjectionMap(sGroupsProjectionMap); 4680226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (groupIdString != null) { 4681226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups._ID + "=" + groupIdString); 4682226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4683226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountName = uri.getQueryParameter(Groups.ACCOUNT_NAME); 4684226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountType = uri.getQueryParameter(Groups.ACCOUNT_TYPE); 4685226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!TextUtils.isEmpty(accountName)) { 4686226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups.ACCOUNT_NAME + "=" 4687226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4688226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + Groups.ACCOUNT_TYPE + "=" 4689226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 4690226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4691226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 4692226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana null, null, updatedSortOrder); 4693226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToFirst(); 4694226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4695226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4696226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public void close() { 4697226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4698226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("closing when already closed"); 4699226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4700226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = true; 4701226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.close(); 4702226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4703226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4704226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public boolean hasNext() throws RemoteException { 4705226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4706226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 4707226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4708226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4709226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return !mEntityCursor.isAfterLast(); 4710226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4711226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4712038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4713038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4714038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4715038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4716038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4717038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4718e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4719226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public Entity next() throws RemoteException { 4720226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4721226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 4722226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4723226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!hasNext()) { 4724226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 4725226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4726226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4727226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 4728226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4729226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final long groupId = c.getLong(COLUMN_ID); 4730226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4731226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana // we expect the cursor is already at the row we need to read from 4732226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ContentValues groupValues = new ContentValues(); 4733226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 4734226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 4735226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups._ID, groupId); 4736226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 4737226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 4738226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 4739226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 4740226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 4741226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 4742226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 47437a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC1, c.getString(COLUMN_SYNC1)); 47447a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC2, c.getString(COLUMN_SYNC2)); 47457a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC3, c.getString(COLUMN_SYNC3)); 47467a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC4, c.getString(COLUMN_SYNC4)); 47477a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYSTEM_ID, c.getString(COLUMN_SYSTEM_ID)); 474894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana groupValues.put(Groups.DELETED, c.getLong(COLUMN_DELETED)); 47497a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.NOTES, c.getString(COLUMN_NOTES)); 47501a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey groupValues.put(Groups.SHOULD_SYNC, c.getString(COLUMN_SHOULD_SYNC)); 4751226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Entity group = new Entity(groupValues); 4752226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4753226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToNext(); 4754226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4755226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return group; 4756226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4757226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4758226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4759a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 47607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 47617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 4762568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 4763568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 47647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 47657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 47665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: 47675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: 47687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 47695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (match == RAW_CONTACTS_ID) { 47707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 47717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 47727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 477346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana return new RawContactsEntityIterator(this, uri, contactsIdString, 477446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana selection, selectionArgs, sortOrder); 4775226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS: 4776226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS_ID: 4777226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String idString = null; 4778226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (match == GROUPS_ID) { 4779226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana idString = uri.getPathSegments().get(1); 4780226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4781226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4782226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return new GroupsEntityIterator(this, idString, 4783226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana uri, selection, selectionArgs, sortOrder); 47847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 47857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 47867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 47877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 47887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 47894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 47904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4791a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 47924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4793b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4794b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP: 4795be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 4796b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4797b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4798b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4799f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 4800f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 4801b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4802be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4803b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4804b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4805508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4806b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 480748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 480848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 480948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 481048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 481148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 481248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 481348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 481448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 481548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 481648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 481748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 481848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4819b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4820b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4821b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4822b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4823b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4824b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4825b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4826b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4827c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4828c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4829c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4830c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 483161efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 483261efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 48334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 483625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private void setDisplayName(long rawContactId, String displayName, int bestDisplayNameSource) { 48373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 483825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindString(1, displayName); 48393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 484025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindNull(1); 48413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 484225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(2, bestDisplayNameSource); 484325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(3, rawContactId); 484425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 48453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 48463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 484773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 484873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 484973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 485073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 4851a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.add(rawContactId); 485273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 485373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4854c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4855c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 4856c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 4857c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4858c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4859c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4860653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 4861c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 4862653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 4863653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 4864c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 4865c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4866c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 4867c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4868c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 4869c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 4870c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4871c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4872c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4873653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 4874c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 4875653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 4876653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 4877c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 4878c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4879ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4880f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 4881f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 4882f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4883f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4884f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4885f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); 4886f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (tokens.length == 0) { 4887f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4888f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4889f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4890f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String address = tokens[0].getAddress(); 4891f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int at = address.indexOf('@'); 4892f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (at != -1) { 4893f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov address = address.substring(0, at); 4894f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4895f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4896f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4897f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 4898f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4899f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4900f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4901f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 4902f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4903f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 4904f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 4905f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4906f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4907f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4908f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4909f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 4910f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4911f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4912a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 4913a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 4914a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 4915a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4916a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 4917a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4918a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 4919a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4920a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 4921a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4922a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4923f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4924f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name) { 4925f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name); 4926f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4927f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4928315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private interface NicknameLookupPreloadQuery { 4929315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 4930315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4931315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String[] COLUMNS = new String[] { 4932315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov NicknameLookupColumns.NAME 4933315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov }; 4934315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4935315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int NAME = 0; 4936315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4937315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4938315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov /** 4939315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * Read all known common nicknames from the database and populate a Bloom 4940315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * filter using the corresponding hash codes. The idea is to eliminate most 4941315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * of unnecessary database lookups for nicknames. Given a name, we will take 49423684089aba82df3f7a0c111e7c96ed8b0380e57aDmitri Plotnikov * its hash code and see if it is set in the Bloom filter. If not, we will know 4943315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * that the name is not in the database. If it is, we still need to run a 4944315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * query. 4945315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * <p> 4946315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * Given the size of the filter and the expected size of the nickname table, 4947315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * we should expect the combination of the Bloom filter and cache will 4948315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov * prevent around 98-99% of unnecessary queries from running. 4949315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov */ 4950315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private void preloadNicknameBloomFilter() { 4951315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov mNicknameBloomFilter = new BitSet(NICKNAME_BLOOM_FILTER_SIZE + 1); 4952315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4953315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupPreloadQuery.TABLE, 4954315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov NicknameLookupPreloadQuery.COLUMNS, 4955315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov null, null, null, null, null); 4956315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov try { 4957315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int count = cursor.getCount(); 4958315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov for (int i = 0; i < count; i++) { 4959315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov cursor.moveToNext(); 4960315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String normalizedName = cursor.getString(NicknameLookupPreloadQuery.NAME); 4961315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int hashCode = normalizedName.hashCode(); 4962315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov mNicknameBloomFilter.set(hashCode & NICKNAME_BLOOM_FILTER_SIZE); 4963315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4964315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } finally { 4965315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov cursor.close(); 4966315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4967315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4968315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4969315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4970f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4971f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Returns nickname cluster IDs or null. Maintains cache. 4972f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4973f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4974315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int hashCode = normalizedName.hashCode(); 4975315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov if (!mNicknameBloomFilter.get(hashCode & NICKNAME_BLOOM_FILTER_SIZE)) { 4976315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov return null; 4977315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 4978315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 4979f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SoftReference<String[]> ref; 4980f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4981f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4982f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (mNicknameClusterCache.containsKey(normalizedName)) { 4983f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = mNicknameClusterCache.get(normalizedName); 4984f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (ref == null) { 4985f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return null; 4986f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4987f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = ref.get(); 4988f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4989f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4990f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4991f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (clusters == null) { 4992f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = loadNicknameClusters(normalizedName); 4993f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = clusters == null ? null : new SoftReference<String[]>(clusters); 4994f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4995f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNicknameClusterCache.put(normalizedName, ref); 4996f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4997f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4998f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4999f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5000f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5001315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov private interface NicknameLookupQuery { 5002315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 5003315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 5004315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov String[] COLUMNS = new String[] { 5005315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov NicknameLookupColumns.CLUSTER 5006315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov }; 5007315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 5008315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov int CLUSTER = 0; 5009315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov } 5010315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 5011f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] loadNicknameClusters(String normalizedName) { 5012b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 5013f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 5014f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupQuery.TABLE, NicknameLookupQuery.COLUMNS, 5015f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.NAME + "=?", new String[] { normalizedName }, 5016f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov null, null, null); 5017f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov try { 5018f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int count = cursor.getCount(); 5019f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (count > 0) { 5020f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = new String[count]; 5021f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov for (int i = 0; i < count; i++) { 5022f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.moveToNext(); 5023f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters[i] = cursor.getString(NicknameLookupQuery.CLUSTER); 5024f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5025f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5026f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } finally { 5027f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.close(); 5028f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5029f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 5030f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5031f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5032f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 5033f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5034f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 5035f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 5036f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5037f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5038f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5039f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 5040f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 5041f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 5042f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5043f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5044f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5045f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 5046f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return ContactsProvider2.this.getCommonNicknameClusters(normalizedName); 5047f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5048f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5049f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5050f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5051f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 5052f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5053f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 5054f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 1, rawContactId); 5055f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 2, dataId); 5056f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 3, lookupType); 5057f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 4, name); 5058f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 5059f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5060f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5061f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5062f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 5063f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5064f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 5065f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupDelete, 1, dataId); 5066f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 5067f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5068f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 50692d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 5070d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5071d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 5072d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 5073d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 5074d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 5075d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 5076d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 5077e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 5078d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN(" 5079d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 5080d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 5081d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NICKNAME + "," 5082d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.ORGANIZATION + "))"); 5083e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 5084e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 50855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 5086c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5087c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 5088c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 5089c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5090c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 5091a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 5092c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit) { 509320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), limit, 509420938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov true); 50955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 50965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 50975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 509820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String limit, boolean allowEmailMatch) { 5099d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5100d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + NameLookupColumns.RAW_CONTACT_ID + 5101d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5102d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 5103d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 51045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 5105a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 5106a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 5107a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 510820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov + NameLookupType.ORGANIZATION); 510920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 511020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 511120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 511220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(")"); 51133de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 5114c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limit != null) { 5115c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(" LIMIT ").append(limit); 5116c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5117c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(")"); 5118ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5119ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 51204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 51214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 51224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 51234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 5124b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 5125b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 5126b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 5127b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 5128b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 51294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 51304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 5131b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 5132b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5133b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5134caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 5135caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 5136caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 5137caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 5138df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 5139df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 5140caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 5141caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 5142caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5143caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 51446f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 5145caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 51466f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 5147caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 51484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 5149