ContactsProvider2.java revision ea029fd79225640e49be82457b83b6b3a0279fd0
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; 56627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.IContentService; 57568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 59627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 6067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 613de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.content.SharedPreferences.Editor; 62b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 64ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 65a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 66b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 67b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 70c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 726ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 73d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 74b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 750e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 76d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 773d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 78508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 793de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 803de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.LiveFolders; 813de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.OpenableColumns; 823de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.SyncStateContract; 83b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 843de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 853de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 863de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 873de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 883de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 893de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 9082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 92ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 93ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 97de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 98b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 994097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 10067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 101a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 102a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 103f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Token; 104f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer; 105c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 107d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 108b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 109d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 110d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 111f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport java.lang.ref.SoftReference; 1127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 114b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1150e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 117622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 118b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1190e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 120ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1265b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 127caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 128bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 129bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 130bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 132619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 133619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 134619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1453d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1460e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1470e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 148a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1505e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final String TIMES_CONTACED_SORT_COLUMN = "times_contacted_sort"; 1515e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 152d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 1535e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar + TIMES_CONTACED_SORT_COLUMN + " DESC, " 1549b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 155d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 156d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 157d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 158d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 159d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 160d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 169f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 1704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 17446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 1754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1766bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1776bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 178ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 17948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 18048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 18148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 18248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 18348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 18448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 18548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 18648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 187a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1886bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1896bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 190b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 191b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 192b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 19382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 19482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 1951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 19631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 19731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 198eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 199eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 200ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 201ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 202ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 203ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 20435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 205b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 20635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 207c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 208c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 209c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2101b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2111b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2121b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2131b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2141b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 21546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 21646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 21767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private interface ContactsQuery { 2185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final String TABLE = Tables.RAW_CONTACTS; 2199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 22067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2216cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2226cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 2236cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 224ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 225ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 22767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_NAME = 1; 22867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_TYPE = 2; 22967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 23067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 231d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 232f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 233f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 234f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 23567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 23667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2376cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 239f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 240ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 241ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 242d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 24367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 244d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 245ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private interface DisplayNameQuery { 24867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final String[] COLUMNS = new String[] { 2513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 253f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 254a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka Organization.TITLE, 2553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 0; 2583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 1; 259a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public static final int DATA = 2; 260a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public static final int TITLE = 3; 2613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 26467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 271f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 27288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 27388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 27488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 27588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 27688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 27788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 27888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 279f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 2803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 28214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 286f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 2873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 28914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 290321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 29120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 29220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 293321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 294321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 29520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 29620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 297f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 298f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private interface NicknameLookupQuery { 299f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 300f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 301f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] COLUMNS = new String[] { 302f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.CLUSTER 303f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov }; 304f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 305f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int CLUSTER = 0; 306f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 307f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 30819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 30919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 31019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 31119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 31219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.DELETED 31319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 31419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 31519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 31619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 31719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 31825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private static final HashMap<String, Integer> sDisplayNameSources; 3193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov static { 32025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources = new HashMap<String, Integer>(); 32125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(StructuredName.CONTENT_ITEM_TYPE, 32225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.STRUCTURED_NAME); 323a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sDisplayNameSources.put(Nickname.CONTENT_ITEM_TYPE, 324a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka DisplayNameSources.NICKNAME); 32525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Organization.CONTENT_ITEM_TYPE, 32625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.ORGANIZATION); 32725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Phone.CONTENT_ITEM_TYPE, 32825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.PHONE); 32925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Email.CONTENT_ITEM_TYPE, 33025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.EMAIL); 3313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 33231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 333c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 334df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 335caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 33671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 33771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 33871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 33971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 34071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 34171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 34271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 34371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 34471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 34571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 34671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 34771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 34871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 34971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 350038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 351038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 352e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 3545e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 3555e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentStarredProjectionMap; 3565e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentFrequentProjectionMap; 357f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 358f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final HashMap<String, String> sContactsVCardProjectionMap; 359ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 360d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 36146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** Contains the columns from the raw contacts entity view*/ 36246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final HashMap<String, String> sRawContactsEntityProjectionMap; 3634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3679261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 368e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 369ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 370ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 371ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 372ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 373373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 374b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 375eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 376eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 37782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 37882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 3791b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3801b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 382c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 383c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 385c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 386ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton /** Precompiled sql statement for incrementing times contacted for a contact */ 387ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton private SQLiteStatement mContactsLastTimeContactedUpdate; 3883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 38925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 39073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** Precompiled sql statement for marking a raw contact as dirty */ 39173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private SQLiteStatement mRawContactDirtyUpdate; 39282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 393a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 394f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 395f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 396a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 397a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 398a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 3990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 400a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 401a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 402f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 403f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 404f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 405f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 4064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 4074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 408a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 409d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 410d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 411d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 4123653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 4133653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 4142d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 4152d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 4163653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 4175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 4185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 4195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 420f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 4215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 422ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 423ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 4245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 4253653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4285ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 42946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 43046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 43146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 432b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 435ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 43648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 438ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 44048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 444ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 44548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 447ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 448ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 449ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 450ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 45135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 452b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 453b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 45435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 455a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 456b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 457b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 458b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 459b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 461eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 462eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 46382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 46482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 4651f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 466c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 467c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 468c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 469c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 470c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 471c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 472c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 4771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 4781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 4791b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 4801b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 48119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 48219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 48319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 484038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 485038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 486e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 4884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 4894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 4904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 496f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 4974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 499f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 5003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 5013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 5023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 5033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 5043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 5053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 5063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 5073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 5083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 5093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 5103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 5113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 5123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 5133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 5145e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5155e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5165e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Long.MAX_VALUE + " AS " + TIMES_CONTACED_SORT_COLUMN); 5175e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5185e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5195e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5205e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Contacts.TIMES_CONTACTED + " AS " + TIMES_CONTACED_SORT_COLUMN); 5215e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 522f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap = Maps.newHashMap(); 523f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 524d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 525f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "0 AS " + OpenableColumns.SIZE); 5264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 5284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 5294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 5354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 5364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 5374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 5384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 5394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 5404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 5414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 5424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 5434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 5444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 5454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 5464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 5472815f58f72f109790585931f601a63ddc02536a5Evan Millar 5484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 5494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 5504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 5514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 5574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 5584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 5594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 5604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 5614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 5624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 5634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 5644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 5654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 5664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 5674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 5684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 5694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 5704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 5714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 57582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 5764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 58156d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 589a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 5904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 591a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 59246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana HashMap<String, String> columns; 59346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns = new HashMap<String, String>(); 59446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts._ID, RawContacts._ID); 59546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 59646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 59746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 59846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 59946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.VERSION, RawContacts.VERSION); 60046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 60146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DELETED, RawContacts.DELETED); 602bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey columns.put(RawContacts.IS_RESTRICTED, RawContacts.IS_RESTRICTED); 60346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 60446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 60546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 60646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 60746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 60846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.MIMETYPE, Data.MIMETYPE); 60946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA1, Data.DATA1); 61046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA2, Data.DATA2); 61146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA3, Data.DATA3); 61246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA4, Data.DATA4); 61346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA5, Data.DATA5); 61446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA6, Data.DATA6); 61546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA7, Data.DATA7); 61646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA8, Data.DATA8); 61746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA9, Data.DATA9); 61846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA10, Data.DATA10); 61946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA11, Data.DATA11); 62046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA12, Data.DATA12); 62146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA13, Data.DATA13); 62246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA14, Data.DATA14); 62346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA15, Data.DATA15); 62446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC1, Data.SYNC1); 62546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC2, Data.SYNC2); 62646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC3, Data.SYNC3); 62746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC4, Data.SYNC4); 62846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 62946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.STARRED, Data.STARRED); 63046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 63146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 63246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 63346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 63446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana sRawContactsEntityProjectionMap = columns; 63546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 6363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 6373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 6383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 6393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 6403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 6413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 6423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 6463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 6483296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 6493296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6503296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 6513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.PRESENCE, 6523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 6533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS, 6543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 6553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 6563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 6573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 6583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 6593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_LABEL, 6603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 6613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_ICON, 6623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 6633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 6645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 6655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 6665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 6675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 6685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 6695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 6705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 6715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 6725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 6735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 6745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 6755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 6765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 6775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 6785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 6795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 6805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 6815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 6825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 6835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 6845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 6855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 6865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 6875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 6885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 6895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 6905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 6915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 6925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 6938f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 6945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 6955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 6965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 6975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 6985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 6995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 7005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 701a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 7025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 7035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 7045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 7053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 7063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 7073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 7083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 7093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 7103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 7113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 7133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 7153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 7173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 7183296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7193296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 7203296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 7213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 7223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS, 7233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 7243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 7253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 7273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 7293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 7313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 7323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 733e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 734e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 735e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_ID + " AS " + PhoneLookup._ID); 73656d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 73756d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar Contacts.LOOKUP_KEY + " AS " + PhoneLookup.LOOKUP_KEY); 738e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 739e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + PhoneLookup.DISPLAY_NAME); 740e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 741e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 742e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 743e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 744e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " + PhoneLookup.TIMES_CONTACTED); 745e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 746e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_STARRED + " AS " + PhoneLookup.STARRED); 747e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 748e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 749e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 750e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.PHOTO_ID + " AS " + PhoneLookup.PHOTO_ID); 751e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 752e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " + PhoneLookup.CUSTOM_RINGTONE); 753e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 754e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.HAS_PHONE_NUMBER + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 755e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 756e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 757e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 758e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 759e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 760e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 761e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 762e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 763e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 7649261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 765ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 766ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 76789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 768035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 769035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 7709261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 7719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 7729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 77389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 774ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 77567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 776ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 7773cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 77894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 7793cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 78038446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 78189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 78289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 78389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 78489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 785ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 786ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 7876cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 788ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 789ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 790d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 791d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 792ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 793ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 794ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 795d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 796d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 797ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 798f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 799ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 800ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 801b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 802b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 803b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 804b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 8050c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 8060c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 807b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 808b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 809eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 810eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 811eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 812eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 813eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 814eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 815341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 816341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 817341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 818fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 819341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 820341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 821341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 82268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 82368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 82468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 82568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 82668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 827e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 82868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 82968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 83068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 831eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 832eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 833373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 8344dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 8350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 8360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 83782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 83882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 83982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 84070c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 84170c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 84282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 84382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 84482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 84582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 8460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 8470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 8480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 8490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 8500a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 85182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 85219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 8531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 8541b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 8551b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 8561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 8571b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 8581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 8591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 8601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 8611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 8621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 8631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 8644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 8654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 8663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 8673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey map.put(toField, fromField + " AS " + toField); 8683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 8693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 8703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 8723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 8743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 876653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 8773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 8793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 880a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 881a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 882a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 883a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 884a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 885a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 886a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 887a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 8883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 890653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 891653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 892b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 893653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 894653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 895653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 896653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 8973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 8993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 901e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 902e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 903e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 904e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 905653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 906e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 907e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 908e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 9093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 9133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 9143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 915653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 916f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 91714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 91814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 919653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 920653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 921653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 922653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 923653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 924653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 925653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 926653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 927653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 928653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 929653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 930653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 931653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 932653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 933653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 934653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 935653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 936653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " = " + dataId, null); 937653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 938653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 939f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 940653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 941653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 9423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 94514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 94614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 94714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 9483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 9493296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 9503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 9515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 9523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 9543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 9575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long newPrimaryId = findNewPrimaryDataId(db, rawContactId); 9583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (newPrimaryId != -1) { 95914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov setIsPrimary(rawContactId, newPrimaryId, getMimeTypeId()); 9603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected long findNewPrimaryDataId(SQLiteDatabase db, long rawContactId) { 964e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 965e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 9665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Cursor c = queryData(db, rawContactId); 9673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 968e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 96914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 970f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 971e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 972e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 973e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 974e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 9753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 9773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 9783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 979e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return primaryId; 980e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 981e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 982e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 983e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 984e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 985e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 986e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 987e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 9883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected Cursor queryData(SQLiteDatabase db, long rawContactId) { 99114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return db.query(DataDeleteQuery.TABLE, DataDeleteQuery.CONCRETE_COLUMNS, 99214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId + 99314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " AND " + MimetypesColumns.MIMETYPE + "='" + mMimetype + "'", 9943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov null, null, null, null); 9953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 99725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 9983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String bestDisplayName = null; 99925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 100025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov 100167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Cursor c = db.query(DisplayNameQuery.TABLE, DisplayNameQuery.COLUMNS, 10025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId, null, null, null, null); 10033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 10043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov while (c.moveToNext()) { 10053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String mimeType = c.getString(DisplayNameQuery.MIMETYPE); 1006a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1007a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // Display name is at DATA1 in all type. This is ensured in the constructor. 1008a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String name = c.getString(DisplayNameQuery.DATA); 1009a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (TextUtils.isEmpty(name) 1010a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka && Organization.CONTENT_ITEM_TYPE.equals(mimeType)) { 1011a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka name = c.getString(DisplayNameQuery.TITLE); 10123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1013a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka boolean primary = StructuredName.CONTENT_ITEM_TYPE.equals(mimeType) 1014a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || (c.getInt(DisplayNameQuery.IS_PRIMARY) != 0); 10153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 101601911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (name != null) { 101725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov Integer source = sDisplayNameSources.get(mimeType); 101801911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (source != null 101901911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov && (source > bestDisplayNameSource 102001911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov || (source == bestDisplayNameSource && primary))) { 102125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov bestDisplayNameSource = source; 10223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov bestDisplayName = name; 10233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 10283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 10293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 103125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov setDisplayName(rawContactId, bestDisplayName, bestDisplayNameSource); 1032285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1033285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateDisplayName(db, rawContactId); 1034285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 10353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1036a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1037a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1038a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return true; 1039a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1040622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1041622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1042622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 1043622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * as baseline, but augmented with any updates. 1044622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1045622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 1046622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 1047622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 1048622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=" + dataId, 1049622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey null, null, null, null); 1050622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 1051622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 1052622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 1053622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 1054622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.put(key, cursor.getString(i)); 1055622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1056622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1057622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 1058622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 1059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1060622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 1061622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 1062622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 10663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 10683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1073622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 10743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1075622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 10763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1077622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 10783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 10815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1082622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 108314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 108414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 108514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1086f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1087f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 108825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 108914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 109014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 109114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 109214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 109314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1094f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1095622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1096622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1097cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1098622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1099622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 110014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1101f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 110214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1103f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 1104f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1105f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1106f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 110714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 110825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 110914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 111014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 111114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 111214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 111314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 111414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 111514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 111614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 111714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1118f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 111925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 112014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 11213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1124622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 11253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1126622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1127622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1128622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1129622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 11303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1131622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1132622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1133622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1134622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1135622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1136622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1137622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 113867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1139622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 114067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 114167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1142622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1143622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 11448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1145622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1146622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 114767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 114867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 114967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 115067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 115167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 115267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 11538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1154622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 1155622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(name); 1156622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 1157622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1158622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1159622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1160622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1161622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1162622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1163622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1164622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1165622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1166622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1167622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1168622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1169622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1170622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1171622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1172622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1173622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1174622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1175622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1176622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1177f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1178622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1179622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1180622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1181f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1182622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1183622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1184622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1185622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1186622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1187622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1188622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1189622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1190622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1191622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1192622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1193622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1194622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1195622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1196622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1197622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1198622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1199622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 120067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 120167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 120267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 120367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1204622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1205622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1206622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1207622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1208622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1209622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 121067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 121167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 121267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1213622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1214622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1215622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 12163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 12213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 12233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 12243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 12263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 12273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 12283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 12293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1233622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1234622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1235622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1237622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1238622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1239f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1240622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1241622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1242622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1243f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1244622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1246622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1247622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1248622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1249622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1250622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1251622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1252622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1253622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 12543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1255622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1256622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1257622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1258622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1259622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 12603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 12643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 12663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 12673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1271a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1272a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1273a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1274a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1275a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 127625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1277a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1278a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 12793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 128214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1283f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1284a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1285a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1286a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 128714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 128814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1289f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 129014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1292a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 1293a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 129414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 129514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 129714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1298a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 129914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 130014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 130114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 130225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1303a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 130414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 130514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 130614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 130714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 13083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 13093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 13103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 13113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 13123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 13133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 13143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1316a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1317a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1318a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1319a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1320a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 13213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1323e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1324e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1325e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1326e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1327e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1328e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1329e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 13305ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 133114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 133214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 133314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 133414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 133525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1336f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 133714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 133814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 133914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 134014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 134114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1342f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 134314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 134414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 134514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 134614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1347f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 134814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1349f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1350f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 135125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 135214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 135314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 135414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 135514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 135614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 135714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 135814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 135914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 136014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1361f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 136225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 136314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1364e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1365e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1366e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1367e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1368e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1369e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1370e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1371e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1372e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1373e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1374e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1375e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1376e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1377e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 137814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 137914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 138014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 138114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 138214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 138314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 138414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 138514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 138614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 138714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 138814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 138914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 139025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1391f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 139214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 139314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 139414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 139514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 139614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1397f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 139814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 139914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 140014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 140114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1402f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 140314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1404f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1405f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 140625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 140714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 140814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 140914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 141014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 141114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 141214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 141314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 141414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 141514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1416f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 141725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 141814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 141914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 142014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 142114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 14223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 14233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 14253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 14263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 14295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 14300b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 14310b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 14320b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 14330b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1434653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14350b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1436653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14370b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1438285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 143925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 14400b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 14410b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 14420b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1443653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1444653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1445653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1446653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1447653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1448f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 144914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 145014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 14510b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 14520b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 14530b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1454653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1455f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1456653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 14570b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1458285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 145925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 14600b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 1461f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 14620b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 146314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 146414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 146614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 146714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 146814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 146914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 147014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 147114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 147214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1473285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 147425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 147514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1476653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1477653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1478653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1479e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1480e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1481e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1482e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1483653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1484653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1485653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1486e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1487653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1488653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1489e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1490653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 14915ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1492653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1493e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 1494653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1495653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1496653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=" + dataId, null); 1497e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 14983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 15013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 15023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 15033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 15043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 15053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 15063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 15073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 15083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 15093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 15103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 15113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 15123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1516653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1517653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1518653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1519653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1520653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1521653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1522653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1523653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1524653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 15250be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 15260be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15270be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1528653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1529653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1530653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1531653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1532f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 153314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1534653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1535f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 15360be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15370be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 15380be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 15390be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 15400be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 15410be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 15420be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 15430be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 15440be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 15450be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 15460be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 15470be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1548b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 15490be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1550b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 15510be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1552653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1553653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1554653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1555653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1556653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1557653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1558653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1559653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1560653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1561653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1562653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1563653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1564653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1565653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1566653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1567653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1568653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1569653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1570653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1571653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1572653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1573653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1574653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1575653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1576653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId); 1577653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1578653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1579653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1580653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1581a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1582a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1583a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1584a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1585a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1586653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1587653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1588a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1589a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1590a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1591a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1592a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1593a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1594a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1595a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1596a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1597285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1598285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1599285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1600a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1601a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1602a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1603a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1604a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1605f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1606a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1607f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1608a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1609a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1610a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1611a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1612a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1613a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1614a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1615a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1616a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1617a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1618a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1619a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1620a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1621a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1622a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1623a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1624a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1625a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 16263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 162753056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 1628b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 162931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 16304097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1631f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1632f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private HashMap<String, SoftReference<String[]>> mNicknameClusterCache = 1633f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov new HashMap<String, SoftReference<String[]>>(); 1634622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1635622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1636622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1637f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1638a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1639a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 164020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 164120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1642ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 164373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private boolean mImportMode; 164473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1645b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mInsertedRawContacts = Sets.newHashSet(); 1646b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1647b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1648de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 16491a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 16501a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 165181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 165281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 1653a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 165453056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 1655a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1656a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1657a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1658a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 1659a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 166053056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 166153056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 1662a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 16634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 16644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 16654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1666de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1667ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1668ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1669ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1670ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1671ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1672ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1673ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 167435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1675ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 1676de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1677b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1678a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1679b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1680b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper, mAggregationScheduler); 16810e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1682a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1683b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 1684653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1685c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1686653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1687653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1688653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1689653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1690653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1691c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1692653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1693653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1694653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1695653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1696653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1697653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1698653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1699653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1700653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1701653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1702653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1703ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate = db.compileStatement( 1704ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton "UPDATE " + Tables.CONTACTS + 1705ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton " SET " + Contacts.LAST_TIME_CONTACTED + "=? " + 1706ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton "WHERE " + Contacts._ID + "=?"); 1707a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 170825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate = db.compileStatement( 170925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 171025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " SET " + RawContactsColumns.DISPLAY_NAME + "=?," 171125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov + RawContactsColumns.DISPLAY_NAME_SOURCE + "=?" + 171225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 17133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 171473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 171573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + RawContacts.DIRTY + "=1 WHERE " + RawContacts._ID + "=?"); 171673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1717a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate = db.compileStatement( 1718a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.CONTACTS 1719a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1720a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1721a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1722a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1723a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1724a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1725a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1726a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1727a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1728a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 17290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 17300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1731a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LIMIT 1)" 1732a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1733e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1734622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Locale locale = Locale.getDefault(); 173528f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 173628f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 173728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 173828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 1739622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey context.getString(com.android.internal.R.string.common_name_conjunctions), 1740622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey locale); 1741f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 1742622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mPostalSplitter = new PostalSplitter(locale); 17434097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1744f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1745f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1746f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1747f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1748f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1749f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1750f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1751a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert = db.compileStatement( 1752a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1753a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 1759a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1760a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace = db.compileStatement( 1761a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1762a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 17630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 17640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 17650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 17660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 17670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 17680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1769a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1770a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp = db.compileStatement( 1771a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 17730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 1774a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 17750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 17760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 17770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate = db.compileStatement( 17780a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 17790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 17800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 17810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 17820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1783a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1784a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete = db.compileStatement( 1785a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1786a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1787a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 17883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 17893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1790e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 17913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 17923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 179367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 179467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 17953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 17963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 179714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 17983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 17993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1800622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1801622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1802a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1803a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 18043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 18053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1806568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 18073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1808568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1809c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov verifyAccounts(); 181070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 1811f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1812f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 18131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 18144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 18154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1816c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 1817c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1818c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1819c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 1820c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 182131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1822de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1823b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1824b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 182531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 182631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1827285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov /* package */ ContactAggregationScheduler getContactAggregationScheduler() { 1828285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mAggregationScheduler; 1829285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1830285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1831013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1832013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1833013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1834013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 18353d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 18363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 18383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1840568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1841568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1842568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1843568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1844568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1845568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1846568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1847568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1848568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1849ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1850568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1851568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1852568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1853568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1854568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1855568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1856568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1857568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1858568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1859568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1860ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1861ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1862568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov scheduleContactAggregation(); 1863568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1864568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1865568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1866568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1867568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1868568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1869568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 18703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1871568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1872568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 18733d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 18753d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 18763d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 18773d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 18783d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 18793d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 18803d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18813d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 18833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1884568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 18850e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 18863d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 188773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = true; 18883d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 18893d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 18900e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(aggregatorEnabled); 18913d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 18923d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 18933d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 18943d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 189573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } finally { 189673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = false; 18973d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18983d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18993d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1900a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1901a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 1902a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 1903a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 1904a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1905a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1906a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 1907a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1908a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1909a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1910a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1911a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1912a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1913b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 1914a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1915a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1916568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1917568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 1918568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1919568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1920568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1921568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1922568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1923568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 1924ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 1925ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 1926ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 1927ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 1928ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 1929ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1930ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 1931ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 193281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 1933ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1934ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1935568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1936568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1937568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1938568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1939568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1940568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1941568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1942568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1943568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1944568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1945568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1946568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1947568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1948568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1949568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1950568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1951568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 1952568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1953568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1954568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1955568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1956568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1957568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1958568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 1959568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1960568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1961568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1962568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1964285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1965bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1966b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1967b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1968285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 19691ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1970b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1971b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1972b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1973b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 1974285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 1975b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 1976df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 1977285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1978285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1979285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1980285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 1981bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1982b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1983b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1984285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1985b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 19861ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 19871a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 19881a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 1989b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 19901a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 1991b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1992b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1993b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1994bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1995b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1996b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1997b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long rawContactId : mInsertedRawContacts) { 1998b5a4add17815167d20a90645779df34cdf45280dFred Quintana mContactAggregator.insertContact(mDb, rawContactId); 1999285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2000b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2001b5a4add17815167d20a90645779df34cdf45280dFred Quintana String ids; 2002b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 2003b5a4add17815167d20a90645779df34cdf45280dFred Quintana ids = buildIdsString(mUpdatedRawContacts); 2004b5a4add17815167d20a90645779df34cdf45280dFred Quintana mDb.execSQL("UPDATE raw_contacts SET version = version + 1 WHERE _id in " + ids, 2005b5a4add17815167d20a90645779df34cdf45280dFred Quintana new Object[]{}); 2006b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2007b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2008b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 2009b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 2010b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().update(mDb, id, entry.getValue()); 2011b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2012b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2013b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2014b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2015b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2016b5a4add17815167d20a90645779df34cdf45280dFred Quintana private String buildIdsString(HashSet<Long> ids) { 2017b5a4add17815167d20a90645779df34cdf45280dFred Quintana StringBuilder idsBuilder = null; 2018b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2019b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (idsBuilder == null) { 2020b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder = new StringBuilder(); 2021b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append("("); 2022b5a4add17815167d20a90645779df34cdf45280dFred Quintana } else { 2023b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(","); 2024b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2025b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(id); 2026b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2027b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(")"); 2028b5a4add17815167d20a90645779df34cdf45280dFred Quintana return idsBuilder.toString(); 2029285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2030285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2031285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2032cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 203381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 203481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 203581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 203681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 203781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 203881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 203981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2040cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2041568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2042568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected void scheduleContactAggregation() { 2043dee54bb86f3608730f0b9f37d8982a7f6b280a85Dmitri Plotnikov mContactAggregator.schedule(); 2044568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2045568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2046285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 2047285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mInsertedRawContacts.contains(rawContactId); 2048285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2049285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 20503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 20513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 20523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 20533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 20543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 20553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 20573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 20583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 20594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2060de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2061bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2062b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "insertInTransaction: " + uri); 2063b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2064f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2065f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2066f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2067f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2068a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2069a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 207035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2071a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 207235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2073b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 207435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 207535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2076d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2077d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 20786bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 20796bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 20806bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 20815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2082f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 2083d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov id = insertRawContact(values, account); 2084f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2085a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2086a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2087a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 20885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 20895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2090f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2091f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2092a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2093a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2094a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2095a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2096f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2097f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2098a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2099a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2100a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2101ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2102ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 21035aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertGroup(uri, values, account, callerIsSyncAdapter); 2104f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2105ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2106ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2107ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2108eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 21095aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 211043880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2111eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2112eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2113eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 211482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 211582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 21161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 21171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 21181f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2119a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 212081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2121f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2122a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2123a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 21247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 21257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 21267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2128de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2129a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2130a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2131a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2132035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 2133035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 2134035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 2135035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 2136035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 21377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2138035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 2139035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 21406cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME); 21416cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2142035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 2143035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 2144035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 2145035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 2146035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2147035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 2148035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2149035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 2150df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_NAME, account.name); 2151df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_TYPE, account.type); 2152035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2153035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 21547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 21567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2157d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 21586bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 21596bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 21606bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 21616bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2162d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2163de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 21646bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 21656bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 21666bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2167a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2168a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2169a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2170f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 2171a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2172a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2173d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertRawContact(ContentValues values, Account account) { 2174a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 2175d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov overriddenValues.putNull(RawContacts.CONTACT_ID); 2176f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 21777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 21787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 21797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 21803d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 21813d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 21823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov overriddenValues.put(RawContacts.AGGREGATION_MODE, 21833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DISABLED); 21843d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 21853d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2186023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov long rawContactId = 2187023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, overriddenValues); 2188023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 2189285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2190285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2191285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.add(rawContactId); 2192023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2193a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2194a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2195a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2196a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2197a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2198a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2199a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2200a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2201f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2202a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2203de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2204de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 220567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2206de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 220720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2208de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2209de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2210de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2211b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2212de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2213de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2214508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2215de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2216de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2217de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2218de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2219de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 22204097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2221b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2222de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2223a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2224a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2225a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2226f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2227de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2228a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2229b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2230a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2231a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2232a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2233a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2234a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 22354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 22378e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 22388e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 22398e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 22408e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 22418e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2242b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2243f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 22448e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 22458e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 22468e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 22478e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2248421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 2249f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22508e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 22518e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 22528e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2253b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2254f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 22558e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 22568e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 22578e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2258f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22598e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2260f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2261c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 2262b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 22638e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2264f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 22658e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2266f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2267f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2268f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2269a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 22705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 22719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 22729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 22735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 22749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 22759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 22769261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 22779261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 22789261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 22795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId) { 22809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Account account = null; 22816cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts._ID + "=" 22825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId, null, null, null, null); 22839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 22849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 228567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountName = c.getString(ContactsQuery.ACCOUNT_NAME); 228667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountType = c.getString(ContactsQuery.ACCOUNT_TYPE); 22879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 22889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana account = new Account(accountName, accountType); 22899261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 22929261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 22939261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 22959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 22969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "has a sourceid the the contact must be associate with " 22979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 22989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 22999261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 23009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 23015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 23026cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 23039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2304df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 23059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 23069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 23079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return c.getLong(0); 23089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 23099261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2310df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2311df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 23129261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 23139261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 23149261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 23159261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 23169261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 23179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23189261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return groupId; 23199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 23219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 23229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 23249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 23259261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 232620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 232720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2328f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 232920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 233020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2331de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2332de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 233314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2334de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2335de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 233614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 233714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2338a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2339a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2340f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 234188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 2342a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2343a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2344a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 234588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 234620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 234720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2348de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 234920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 235020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 235120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 235220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 235320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 235488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 235588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 235688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 235720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2358f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 235988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 236088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 236114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=" + dataId, null, 236214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov null); 2363f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 236420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 236520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 236620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 236720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 236820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 236914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 237020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 237120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 237220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 237320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 237420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 237520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 237620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 237720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 237820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 23797a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 238020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 238120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 238220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2383a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2384a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 23858e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2386a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2387a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2388a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 23898e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 239020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 239120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 239220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 239320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 239420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 239520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2396ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2397ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2398b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, Account account, 2399b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov boolean callerIsSyncAdapter) { 2400ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 2401ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 2402ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 2403ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2404ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2405ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 240667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.RES_PACKAGE); 240767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 2408b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov overriddenValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 240967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 241067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.remove(Groups.RES_PACKAGE); 2411ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2412f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 241373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov overriddenValues.put(Groups.DIRTY, 1); 241473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 241573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2416ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey long result = mDb.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 2417ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 24181a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (overriddenValues.containsKey(Groups.GROUP_VISIBLE)) { 24191a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2420ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2421ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2422ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2423ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2424ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 24255aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2426e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 24275aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 24281a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 24291a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2430e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 24311a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 2432e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2433e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2434e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2435ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 243682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 24371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 243882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 243982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 24400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 24414dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 24424dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 24430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 244482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 24454dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 24464dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 24474dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 24484dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 24491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2451dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 2452dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 245382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 2454f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 2455dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 2456dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 2457dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2458f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "="); 2459f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(dataId); 24601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 2461dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 2462dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 24630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 24640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 24650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 24660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2467dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 2468dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 2469dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2470dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 2471f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2472f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 2473f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 2474f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 2475f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2476f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 2477f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 2478f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (") 2479f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2480f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(",") 2481f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2482f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(")" + " AND " + Data.DATA1 + "="); 2483f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2484f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ((" + DataColumns.MIMETYPE_ID + "=") 2485f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2486f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2487f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol); 2488dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2489f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2490f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2491dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2492f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=") 2493f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdEmail) 2494f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append("))"); 2495dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 2496f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=") 2497f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(mMimeTypeIdIm) 2498f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.PROTOCOL + "=") 2499f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(protocol) 2500f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov .append(" AND " + Im.DATA + "="); 2501f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, handle); 2502dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2503f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2504f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 2505dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2506dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 25071f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 250882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 2509f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=") 251082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .append(values.getAsLong(StatusUpdates.DATA_ID)); 2511dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 251270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 2513f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 251470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 25151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 25161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2517de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 2518c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov mSb.toString(), null, null, null, 2519c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 25201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 252167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 25225ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2523e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 25241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 25251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 25261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 25271f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 252931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 253031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 253131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 25321f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 253482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2535a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2536a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2537a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2538a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2539a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2540a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2541a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 254282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2543a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2544a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 254582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 254682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 254782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 254882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 254982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2550a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 255182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 255282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 25531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2554a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2555a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2556a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2557e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 25580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 255982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 256082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 25610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 25620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 25630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 25640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 25650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 25660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 25670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 25680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 25690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 25700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 25710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 25720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2573a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 2574a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 2575a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 257682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 257782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 2578a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 2579a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 25800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 3, status); 25810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 4, resPackage); 25820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 5, iconResource); 25830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 6, labelResource); 2584a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 2585a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 2586a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2587a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 2588a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 25890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 2, status); 25900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 3, resPackage); 25910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 4, iconResource); 25920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 5, labelResource); 2593a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 2594a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 2595a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 25960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 2597a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 25980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 2, status); 2599a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 26000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 4, status); 2601a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 26020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 26030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 1, resPackage); 26040a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 2, iconResource); 26050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 3, labelResource); 26060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 26070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 2608a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2609e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2610e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2611bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2612a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2613a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 2614a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 2615a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 2616a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2617a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2618a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 26191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 26201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 26214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2622de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2623bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2624b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2625b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2626b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2627f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2628f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2629508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2630508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 263135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2632b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 263335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2634b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2635b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2636b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2637b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2638b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2639b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2640cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2641cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2642cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2643cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2644cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2645d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2646d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2647cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 26486bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 26496bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 26502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 26512e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 26522e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 26532e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 26542e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 26552e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 26562e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26572e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 26582e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 26592e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 26602e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26612e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 26622971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 26632971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 26642971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2665e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 26662971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 26672971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 26682971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2669f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana numDeletes += deleteRawContact(rawContactId, callerIsSyncAdapter); 26702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 26722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 26732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 26752971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 26762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 26775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 26782971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2679f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteRawContact(rawContactId, callerIsSyncAdapter); 2680508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2681508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 268220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2683f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2684944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2685f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 268620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 268720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 268848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 268948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 269048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 269148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2692508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2693f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2694f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteData(Data._ID + "=" + dataId, null, callerIsSyncAdapter); 2695ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2696ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2697ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2698f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 26995aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 27002971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27012971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 27022971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 27032971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 27042971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2705e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 27062971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 27072971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 27085aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 27092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27102971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 27112971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 27122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 271381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2714f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 271581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 27162971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2717508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2718508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2719eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 272043880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 27215aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteSettings(uri, selection, selectionArgs); 2722eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2723eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 272482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 27250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 27261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 27271f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 272881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 272981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 27303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 273181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2732508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 27334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 273546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static boolean readBooleanQueryParameter(Uri uri, String name, boolean defaultValue) { 27362971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final String flag = uri.getQueryParameter(name); 27372971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return flag == null 27382971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana ? defaultValue 27392971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana : (!"false".equals(flag.toLowerCase()) && !"0".equals(flag.toLowerCase())); 274094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 274194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 27421c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 2743b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 274494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2745de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 274694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 274794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 274894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 274994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2750f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2751de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 275294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 275394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 275494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2755f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2756de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 275794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 275894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 27591a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 276094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 276194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 276294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 27635aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2764e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 27651a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2766e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2767e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2768e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2769cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 2770cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2771cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null); 2772cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2773cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2774cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2775cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 2776cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2777cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2778cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2779cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2780cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2781cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2782cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2783cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2784f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana public int deleteRawContact(long rawContactId, boolean callerIsSyncAdapter) { 2785f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 278614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2787de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 278833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2789b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 2790cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 279133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 279233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 279333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 27940a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 27950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO delete from both tables: presence and status_updates 27960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 27970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 27980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2799cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 280081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 280181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 2802cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 2803cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 2804cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2805cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2806cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2807cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2808cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 2809cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2810cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 28114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2812de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2813de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 2814bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2815b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2816b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2817b5a4add17815167d20a90645779df34cdf45280dFred Quintana 281835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 281900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 282000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 2821b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 2822b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 2823b5a4add17815167d20a90645779df34cdf45280dFred Quintana Object data = values.get(ContactsContract.SyncStateColumns.DATA); 2824b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 2825b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 2826b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2827b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2828f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2829f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 283000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 283135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2832b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2833b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 2834b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2835b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 2836b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 2837b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2838b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2839b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2840b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2841b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 2842b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 284335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2844d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 28458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 284600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 284700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 284800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2849d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 28508c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 2851c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2852c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2853c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 28542e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 28552e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 28562e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 28572e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 28582e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 28592e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 28602e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 28612e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 28622e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 28638c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 28642e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 28652e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 28662e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 28677d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 28687d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 28697d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 28707d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 28717d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 28727d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 28737d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 28747d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 28757d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 28767d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 287720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2878944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2879f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 288081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2881f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 288281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 288320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 288420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2885c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 288648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 288748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 288848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 288948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2890f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 289181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2892f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 289381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 289400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 289500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 28967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 28975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 28985ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 28994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 29007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 29017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 29027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 29035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 290433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 29054529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 29064529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=" + rawContactId 29074529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 29084529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 290927f039b535f98c1cb1a31207047003235ddaed15Dmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=" + rawContactId, null); 29104529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 29117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 29127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 29137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2914ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 29155aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 2916f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 291781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2918f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 291981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2920ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2921ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2922ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2923ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2924ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 292573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String selectionWithId = (Groups._ID + "=" + groupId + " ") 292673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 29275aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 29285aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 292981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2930f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 293181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2932ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2933ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2934ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2935127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 2936de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 2937b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2938b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2939b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2940eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 29415aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateSettings(uri, values, selection, selectionArgs); 294243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2943eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2944eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2945eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 294681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 294781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2948f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 294981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 295000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 295100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 295200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 29534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 29544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 29555aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 2956f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 295773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 295873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 2959f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 296073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 296173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 296273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 296373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 296473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 296573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 296673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 296773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2968ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 29691a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 29701a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 297194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 29726ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 2973627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 29746ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi final long groupId = ContentUris.parseId(uri); 29756ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 29766ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Groups.ACCOUNT_TYPE}, Groups._ID + "=" + groupId, null, null, 29776ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 29786ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 29796ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 29806ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 29816ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 29826ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 29836ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 29846ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 29856ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 2986627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 29876ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 29886ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 29896ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 29906ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 29916ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 29926ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 29936ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 29946ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 299594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 299694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 299794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2998b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 2999b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 3000e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 30011a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 30021a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3003e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3004e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3005e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3006e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 30074529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 30084529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 30094529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 30104529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 30114529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 301273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 30134529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3014b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 301551bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 30164529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 30174529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 30184529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 30194529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 30204529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 30214529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 30224529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 30234529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 30244529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 30254529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 30264529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 30274529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 30284529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 30294529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 30304529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 303119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final String selection = RawContacts._ID + " = " + rawContactId; 303219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 303319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 303419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 303519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 303619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 303719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka null, null, null, null); 303819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 303919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 304019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 304119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 304219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 304319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 304419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 304519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 304619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 304719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 304819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int count = mDb.update(Tables.RAW_CONTACTS, values, selection, null); 30495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3050433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 30514529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3052433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3053285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 3054285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateLookupKey(mDb, rawContactId); 3055285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 305619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 305719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 305819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka mInsertedRawContacts.add(rawContactId); 305919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 30605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 30615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 306233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 306333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3064321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3065f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 306620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 306720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 306820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 30695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 307020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 307120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 307220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 307320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 307420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3075b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 307620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 307720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 307870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 307970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 308020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 308120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 308220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 308370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 308420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 308570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 308620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 308770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 308820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 308970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 309020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 309120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3092653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 309320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3094653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3095653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 309614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 3097653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 3098653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 3099f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 310020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3101653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 3102653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 310320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 310420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3105653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 310620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 310720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3108f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 3109653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 3110653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 3111321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3112653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 311314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 3114a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3115f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana rowHandler.update(mDb, values, c, callerIsSyncAdapter); 31168e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 3117a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 3118a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 3119a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 31208e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 3121653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 3122321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3123321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 31248c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 31258c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 31268c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 3127b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 31288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 31298c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 31308c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 31318c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 31328c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 31338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 31348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 31358c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 31368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 31378c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 31388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 31398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 31418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 31428c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 3144d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 31458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3146b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3147d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3148b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 3149d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3150b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 3151d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3152b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3154b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3155d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 3156d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3157d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 31588c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 3159d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 3160d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3161d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 31628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 3163c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 31648c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3165c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 3166c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 31678c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=" + contactId, null); 31688c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31698c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 31708c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 31718c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3172b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 31738c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3174b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 31758c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3176b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 31778c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3178b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 31798c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3180b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 31818c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 31828c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 31838c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=" + contactId, null); 3184f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3185d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3186ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton public void updateContactLastContactedTime(long contactId, long lastTimeContacted) { 3187ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 3188ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.bindLong(2, contactId); 3189ba965ceeb86dd9404d43f418daae357bc4afbdcdJeff Hamilton mContactsLastTimeContactedUpdate.execute(); 3190d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3191d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3192127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 3193127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 31940c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 31950c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 319680c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 31970c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 31980c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 31990c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 32000c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 32010c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 32020c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 32030c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 3204b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3205127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 32060c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 32070c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 32080c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=" + rawContactId1 + " AND " 32090c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=" + rawContactId2, null); 32100c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 32116bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 32126bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 32130c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 32140c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 32150c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 32160c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 3217127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 3218127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3219dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 3220dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 3221dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 3222b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 32230c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 32240c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 3225b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId2 = mDbHelper.getContactId(rawContactId2); 32260c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 3227127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3228127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 3229127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 3230127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3231b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3232b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 323370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 3234b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 323570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (mDb == null) return; 323670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 3237627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 3238627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov boolean hasUnassignedContacts[] = new boolean[]{false}; 323970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 324070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 3241627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3242627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.RAW_CONTACTS, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE); 3243627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3244627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.GROUPS, Groups.ACCOUNT_NAME, Groups.ACCOUNT_TYPE); 3245627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3246627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Tables.SETTINGS, Settings.ACCOUNT_NAME, Settings.ACCOUNT_TYPE); 324748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3248627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 3249627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // in the existingAccounts set will be extra accounts whose data must be deleted. 3250627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 3251627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 3252627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 325370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 325470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 325570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 32565f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 3257627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 3258627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3259627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 3260627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 3261627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 3262627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3263627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 3264627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 3265627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "SELECT " + RawContacts._ID + 3266627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 3267627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3268627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 3269627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3270627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 3271627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3272627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 3273627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3274627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 3275627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 3276627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 3277627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3278627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3279627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (hasUnassignedContacts[0]) { 3280627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3281627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Account primaryAccount = null; 3282627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 3283627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (isWritableAccount(account)) { 3284627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov primaryAccount = account; 3285627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov break; 3286627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3287627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3288627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3289627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (primaryAccount != null) { 3290627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {primaryAccount.name, primaryAccount.type}; 3291627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3292627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3293627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 3294627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + RawContacts.ACCOUNT_NAME + "=?," 3295627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=?" + 3296627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + 3297627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL", params); 3298627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3299627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // We don't currently support groups for unsynced accounts, so this is for 3300627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // the future 3301627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3302627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.GROUPS + 3303627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + Groups.ACCOUNT_NAME + "=?," 3304627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + Groups.ACCOUNT_TYPE + "=?" + 3305627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " IS NULL" + 3306627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " IS NULL", params); 3307627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 330870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3309627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3310b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 331170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 331270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 331370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 331470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 331570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3316619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3317619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3318627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 3319627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 3320627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov private void findValidAccounts(Set<Account> validAccounts, boolean[] hasUnassignedContacts, 3321627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String table, String accountNameColumn, String accountTypeColumn) { 3322627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Cursor c = mDb.rawQuery("SELECT DISTINCT " + accountNameColumn + "," + accountTypeColumn 3323627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + " FROM " + table, null); 3324627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 3325627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 3326627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (c.isNull(0) && c.isNull(1)) { 3327627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov hasUnassignedContacts[0] = true; 3328627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } else { 3329627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 3330627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3331627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3332627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 3333627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 3334627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3335627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3336627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3337627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov /** 3338622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 3339622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 334067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 334167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 334267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 334367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 334467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 334567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 334667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 334767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 334867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 334967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 335067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 335167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 3352dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 3353622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 3354dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 3355dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 3356622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3357622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3358dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 3359622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3360622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 33614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 33624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 33634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 3364bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3365bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3366bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 33670b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 3368b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 336935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3370d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 33711f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3372c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3373c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3374619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3375619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3376a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 33774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 337835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3379b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 338035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 338135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3382d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3383763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3384619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3385619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3386619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3387d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 33884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3389763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 33904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + contactId); 33916bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 33926bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 33936bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 33945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 33955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 33965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 33975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 33985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 33995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 34005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 34025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 34035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 34045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3405763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 34065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=" + contactId + " AND " + 34075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.LOOKUP_KEY + "="); 34085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhereEscapeString(lookupKey); 34095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, selectionArgs, sortOrder, 34105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 34115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 34125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 34135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 34165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3418763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 34195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 34205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 34215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3423f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 3424f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 3425f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 3426763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 3427f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 3428f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 3429f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 3430f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 3431f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 3432ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3433763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3434ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 34354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 34364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3437e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 34385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 34394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sb.toString()); 3440ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3441ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3442ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3443ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3444ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3445ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 34464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3447ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3448d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 34494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 34504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3451e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 34525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 34534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 34544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 34554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3456763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3457ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 34585e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 34595e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 34605e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 34615e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar starredProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 34625e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar frequentProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 34635e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 34645e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 34654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 34664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 34674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3468d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 34695e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 34705e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 34714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3472d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3473d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3474d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3475763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 34764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 34774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3478d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 34795e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 34805e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 3481d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3482d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 34834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3484d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3485d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3486d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3487d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 34884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 34894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3490d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3491d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3492d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3493d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3494d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3495d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3496ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3497763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3498b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 349971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 35004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3501b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3502b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3503b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3504b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3505d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 35064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 350782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 35084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 35096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 35106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 351100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3512ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 35133653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 351482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 35153653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 35163653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 35173653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 35183653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 35193653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 35204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 352182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 352289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 35232815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 35242815f58f72f109790585931f601a63ddc02536a5Evan Millar } 35252815f58f72f109790585931f601a63ddc02536a5Evan Millar 352648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 352782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 352848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 352948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 353048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 353148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 353248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3533ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 353482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 353589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3536ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 35374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 35384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 35395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 35405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 35415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 35425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 35435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 35445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 354520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null, false); 35465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 35475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 35495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 35505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 35515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 35525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 35545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 35555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 35565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 35575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 35585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 35595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 35605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 35615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 35634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + sb); 3564ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 35655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3566a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3567a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3568a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 3569ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3570ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3571ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 35724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 357382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 357489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 35754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 35764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 35774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 357848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 357982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 358048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 358148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 358248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 358348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 358448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 35855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 358682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 358789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 35884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 35895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + Email.DATA + "="); 35904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhereEscapeString(uri.getLastPathSegment()); 35914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3592ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3593ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3594ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 35955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 359682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 359789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 35985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 35995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 36005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 36015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 36025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 360320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 360420938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 360520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 360620938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 360720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null, false); 360820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(" OR "); 360920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 36105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 36125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Email.DATA + " LIKE "); 36131e530df9f7e496dc47f77d4323c89bd413b79b64Dmitri Plotnikov sb.append(DatabaseUtils.sqlEscapeString(filterParam + '%')); 36145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 36155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + sb); 36165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 3618a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3619a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3620a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 36215e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 36225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3624ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 362582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 362689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 362789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3628ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3629ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3630ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 363148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 363282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 363348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 363448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 363548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 363648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 363748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 363848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 36395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 3640763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 36414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 36424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 36455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 3646763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 364789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 36484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 36494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 36525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 365382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 365489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=" + rawContactId); 3655e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3656e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3657e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 3658e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 365982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3660e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3661e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3662e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 36634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 366482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 366582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + ContentUris.parseId(uri)); 3666a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3667a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3668a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3669a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 36704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3671a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 3672a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 3673a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 3674e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 3675a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3676a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3677e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 3678b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 3679e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 3680e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 3681e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 3682e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 3683e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 3684a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3685a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3686a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3687ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 3688b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3689ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 369089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3691ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3692ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3693ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3694ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3695ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 3696b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3697ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 369889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(Groups._ID + "=" + groupId); 3699ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3700ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3701ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3702ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 3703b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 3704ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 370589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 370689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 3707ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3708ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3709ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3710b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 37110c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 3712b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 3713b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3714b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3715b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 371631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 3717d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 37182d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 37192d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 37202d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 37212d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 372231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 3723d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 3724d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 372531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 372631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 372731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 372831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3729763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 37307581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 37317581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 37322d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 373331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 373431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3735eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3736eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 3737eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 373889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3739e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3740e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 3741e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 3742b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 3743e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 374482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3745b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3746e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3747e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 374882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3749b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3750e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3751e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3752e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3753eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3754eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3755eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 375682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 37570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 37585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 37595ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 37605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 376182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 37620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 37630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=" + ContentUris.parseId(uri)); 37645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 37655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 37665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 3767c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 3768a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 3769c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3770c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3771c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 3772b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3773b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh(db, contactId, projection); 3774c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3775c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 37761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 3777b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 37791b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37801b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37811b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 3782b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37831b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 37841b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 37851b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37861b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37871b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 3788b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 37901b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 37911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37921b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37931b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 3794b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 379671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 37971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 37981b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37991b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 380046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 380146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 380246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 380346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 380446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 380546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 380646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 380746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 380846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 380946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 381046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 381146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 38124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 3813f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 3814c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 38154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 38164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 38175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 38185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 38215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 38225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 3823038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 3824038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 3825038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 3826038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 38275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 38285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 38294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 38304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 38314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 38324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 38334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 38344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 38355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 38365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 38375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 38385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 38405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 38415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 38425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 38455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 38485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 38495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 38515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 38525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 38535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 38545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 38555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 38565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 38585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 38595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 38605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 38615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 38645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 38655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 38665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 38695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 38705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 38745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 38755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 38785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 38795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 38805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 38815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 38825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 38835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 38845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 38855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 38885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 38895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 38915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 38925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 38935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 38945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 38955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 38965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 38975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 38985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 38995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 39005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 39025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 39035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 39045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 39055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 39095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 39105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 39135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 39165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 39175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 39195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 39205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 39215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 39225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 39235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 39245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 39265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 39275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 39285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 39295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 39325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 39335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 39345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 39355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 39375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 39385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 39425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 39435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 39465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 39475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 39485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 39495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 39515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 39525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 39535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 39565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 39575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 39585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 39605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 39615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 39625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 39635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 39645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 39655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 39665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 39675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 39685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 39695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 39715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 39725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 39735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 39745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 39785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 39795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 39825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 39855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 39865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 39875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 39885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 39895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 39915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 39925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 39945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 39955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 39975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 39985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 39995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 40005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 40015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 40025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 40035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 40045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 40055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 40065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 40085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 40095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 40135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 40145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 40155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 40165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4019763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 4020763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 402182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4022763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4023763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 4024763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4025763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4026d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4027763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4028763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 4029b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 403082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 403182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 403282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 403382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4034b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 403582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 403682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 403782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 403882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 403982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 40403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 40413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 4042a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 40433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 404482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 404582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 404682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 404782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4048ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 4049763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 4050763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 4051763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4052763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 4053763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4054763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4055d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4056763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4057763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 4058763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 4059763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 4060763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 4061763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4062763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 406346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 406446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana // Note: currently, "export only" equals to "restricted", but may not in the future. 406546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana boolean excludeRestrictedData = readBooleanQueryParameter(uri, 406646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.FOR_EXPORT_ONLY, false); 406746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 406846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String requestingPackage = uri.getQueryParameter( 406946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 407046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana if (requestingPackage != null) { 407146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana excludeRestrictedData = excludeRestrictedData 407246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 407346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 407446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 407546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setProjectionMap(sRawContactsEntityProjectionMap); 407646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 407746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 407846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 407982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 408082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 408182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4082d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa // Note: currently, "export only" equals to "restricted", but may not in the future. 4083763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = readBooleanQueryParameter(uri, 4084d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa Data.FOR_EXPORT_ONLY, false); 4085763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4086763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String requestingPackage = uri.getQueryParameter( 4087763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4088763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4089763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar excludeRestrictedData = excludeRestrictedData 4090d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4091763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4092763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4093763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getDataView(excludeRestrictedData)); 409482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 409582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 40963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated presence when requested 4097b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 409882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 40993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 410082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 410182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 410282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 41033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated status updates when requested 4104b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 410582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 410682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 410782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 410882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 410982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 41103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 41113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 411282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 41133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 4114ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 41153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 41163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual presence when requested 41173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 41183296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 41193296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdates.DATA_ID + "=" 41203296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 41213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 41223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 41233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual status updates when requested 41243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, 41253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS, 41263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_RES_PACKAGE, 41273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_ICON, 41283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_LABEL, 41293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_TIMESTAMP)) { 41303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 41313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 41323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 41333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 41343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 413582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 413682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 413782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 4138ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 4139ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 41400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 41410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 41420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4143b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 41440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 41450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4146b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 41470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 41480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 41490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 41500a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 41510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4152b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 41530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 41540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 41550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 41560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 41570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 41580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 41590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 41600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 41610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 41620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setTables(sb.toString()); 41630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 41640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 41650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 41664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 41674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 41684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 41694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 41704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 41714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 41724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 41734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 41744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 41754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 41764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 41774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 41784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4179e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 4180e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 4181e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 4182e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(accountName)) { 4183e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 4184e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4185e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 4186e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 4187e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 4188e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 4189e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 4190e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 4191e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4192e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 4193e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 4194e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 4195e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4196e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4197e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 41987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 4199c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 4200c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 4201c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 4202c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 4203c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 4204c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private String getLimit(Uri url) { 4205c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limitParam = url.getQueryParameter("limit"); 4206c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 4207c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4208c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4209c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 4210c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 4211c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 4212c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 4213c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4214c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4215c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4216c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 4217c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 4218c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4219c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4220c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4221c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4222c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 42235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 42245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 42255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 42265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 42275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 42285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 42295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 42305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 42315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 42325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 42335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 42345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 42355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 42375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 42385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 42395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 42415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 42425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 42445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 42455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 42475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 42485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 42505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 42515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 425300ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 4254d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 425570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 425670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 42576cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 425870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 425970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 426070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 426170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 4262d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 426370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 426467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 42655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 42665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 4267619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4268619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4269619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4270b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 4271b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 4272b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 4273b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 4274d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 4275b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 4276b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 4277b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4278b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4279b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 4280b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4281b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 4282b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 4283b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 4284b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=" + contactId; 4285b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4286b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, null); 4287d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4288d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4289f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 4290d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 4291d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 429214b8a1243ab5c043b35e47527ca1c962064f3771Daisuke Miyakawa final String selection = Contacts._ID + "=" + contactId; 4293d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4294d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 4295d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 4296d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 4297d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 4298d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey outputRawContactsAsVCard(localStream, selection, null); 4299d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 4300d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4301b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4302b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 4303b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("No file at: " + uri); 4304b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4305b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4306b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4307d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 4308d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String VCARD_TYPE_DEFAULT = "default"; 4309d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4310d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4311d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 4312d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 4313d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4314d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 4315d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 4316d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 4317d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 4318d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4319d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 4320d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 4321d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4322d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 4323d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 4324d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 4325b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4326d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 4327d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 4328d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 4329d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4330d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 4331d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4332d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4333d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4334d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 4335d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 4336d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 4337d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4338d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 4339d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 4340d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 4341d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final VCardComposer composer = new VCardComposer(context, VCARD_TYPE_DEFAULT, false); 4342d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 4343d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4344f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 4345d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.init(selection, selectionArgs)) 4346d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 4347d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4348d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 4349d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 4350d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 4351d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4352d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4353d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 4354d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4355b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4356bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4357bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov private static Account readAccountFromQueryParams(Uri uri) { 4358bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String name = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 4359bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String type = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 4360bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 4361bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return null; 4362bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 4363bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return new Account(name, type); 4364bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 4365bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4366bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 4367619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 43687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 43697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 43707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 4371d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static class RawContactsEntityIterator implements EntityIterator { 43727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 43737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 43747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 43757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 43767a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 43777a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 43787a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 43797a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 43807a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 43817a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 43827a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 43837a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 43847a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 43857a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 43867a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 43877a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 43887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 43897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 43907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 43917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 43927a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 43937a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 43947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4}; 43957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 439646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana public static final String[] PROJECTION = new String[]{ 43976cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 43986cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 43996cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.SOURCE_ID, 44006cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.VERSION, 44016cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.DIRTY, 440246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana RawContacts.Entity.DATA_ID, 44037a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RES_PACKAGE, 44047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.MIMETYPE, 44057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 44067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 44077a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 44087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 44097a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 44107a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 44117a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 44127a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 44137a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 44147a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 44157a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 44167a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 44177a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 44187a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 44197a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 44207a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 44217a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 44227a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 44237a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4, 442446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana RawContacts._ID, 44257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.IS_PRIMARY, 44263cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar Data.IS_SUPER_PRIMARY, 44277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA_VERSION, 44287a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana GroupMembership.GROUP_SOURCE_ID, 44297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC1, 44307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC2, 44317a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC3, 443294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana RawContacts.SYNC4, 443338446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey RawContacts.DELETED, 4434c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.CONTACT_ID, 4435bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey RawContacts.STARRED, 4436bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey RawContacts.IS_RESTRICTED}; 4437035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 4438035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 4439035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 4440035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 4441035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 4442035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 4443035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 444467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_RES_PACKAGE = 6; 444567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_MIMETYPE = 7; 444667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA1 = 8; 44477a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_RAW_CONTACT_ID = 27; 44487a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_IS_PRIMARY = 28; 44493cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_IS_SUPER_PRIMARY = 29; 44503cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DATA_VERSION = 30; 44513cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_GROUP_SOURCE_ID = 31; 44523cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC1 = 32; 44533cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC2 = 33; 44543cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC3 = 34; 44553cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC4 = 35; 44563cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DELETED = 36; 44573cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_CONTACT_ID = 37; 44583cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_STARRED = 38; 4459bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey private static final int COLUMN_IS_RESTRICTED = 39; 44607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 446146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana public RawContactsEntityIterator(ContactsProvider2 provider, Uri entityUri, 446246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String contactsIdString, 446346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String selection, String[] selectionArgs, String sortOrder) { 44647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 446546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Uri uri; 44667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 446746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = Uri.withAppendedPath(RawContacts.CONTENT_URI, contactsIdString); 446846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = Uri.withAppendedPath(uri, RawContacts.Entity.CONTENT_DIRECTORY); 446946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } else { 447046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana uri = ContactsContract.RawContactsEntity.CONTENT_URI; 4471035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 447246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana final Uri.Builder builder = uri.buildUpon(); 447346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String query = entityUri.getQuery(); 447446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana builder.encodedQuery(query); 447546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana mEntityCursor = provider.query(builder.build(), 447646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana PROJECTION, selection, selectionArgs, sortOrder); 44777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 44787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4480038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4481038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4482038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4483038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4484038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4485038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4486038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana 44877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 44887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 44897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 44907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 44927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 44937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 44957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 44967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 44977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 44987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 44997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 45017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 45047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 45057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 45067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 45087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 45097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 45127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45137a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final long rawContactId = c.getLong(COLUMN_RAW_CONTACT_ID); 45147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 45167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 45176cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 45186cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 45195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 45206cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 45216cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 45226cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 45237a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC1, c.getString(COLUMN_SYNC1)); 45247a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC2, c.getString(COLUMN_SYNC2)); 45257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC3, c.getString(COLUMN_SYNC3)); 45267a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC4, c.getString(COLUMN_SYNC4)); 452794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana contactValues.put(RawContacts.DELETED, c.getLong(COLUMN_DELETED)); 452838446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey contactValues.put(RawContacts.CONTACT_ID, c.getLong(COLUMN_CONTACT_ID)); 4529c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey contactValues.put(RawContacts.STARRED, c.getLong(COLUMN_STARRED)); 4530bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey contactValues.put(RawContacts.IS_RESTRICTED, c.getInt(COLUMN_IS_RESTRICTED)); 45317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 45327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 45347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 45357a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana if (rawContactId != c.getLong(COLUMN_RAW_CONTACT_ID)) { 45367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 45377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 453823c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// if (c.isNull(COLUMN_CONTACT_ID)) { 453923c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// continue; 454023c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// } 45417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 45427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 454323c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data._ID, c.getLong(COLUMN_DATA_ID)); 45447a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 45457a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 454623c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_PRIMARY, c.getLong(COLUMN_IS_PRIMARY)); 454723c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_SUPER_PRIMARY, c.getLong(COLUMN_IS_SUPER_PRIMARY)); 45487a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 45499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 45509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana dataValues.put(GroupMembership.GROUP_SOURCE_ID, 45519261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.getString(COLUMN_GROUP_SOURCE_ID)); 45529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 45537a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 45547a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana for (int i = 0; i < DATA_KEYS.length; i++) { 45557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 45567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 45577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 45587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 45597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 45607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 45617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 45627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 45637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 45647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 45657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 45667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 45677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 45707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 45717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 45727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 45737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 45757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4576226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana /** 4577226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 4578226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 4579226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana */ 4580226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static class GroupsEntityIterator implements EntityIterator { 4581226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private final Cursor mEntityCursor; 4582226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private volatile boolean mIsClosed; 4583226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4584226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final String[] PROJECTION = new String[]{ 4585226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups._ID, 4586226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_NAME, 4587226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_TYPE, 4588226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.SOURCE_ID, 4589226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.DIRTY, 4590226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.VERSION, 4591226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.RES_PACKAGE, 4592226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE, 4593226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE_RES, 45947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.GROUP_VISIBLE, 45957a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC1, 45967a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC2, 45977a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC3, 45987a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC4, 45997a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYSTEM_ID, 460094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.NOTES, 46011a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey Groups.DELETED, 46021a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey Groups.SHOULD_SYNC}; 4603226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4604226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ID = 0; 4605226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_NAME = 1; 4606226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_TYPE = 2; 4607226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_SOURCE_ID = 3; 4608226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_DIRTY = 4; 4609226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_VERSION = 5; 4610226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_RES_PACKAGE = 6; 4611226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE = 7; 4612226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE_RES = 8; 4613226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_GROUP_VISIBLE = 9; 46147a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 10; 46157a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 11; 46167a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 12; 46177a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 13; 46187a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYSTEM_ID = 14; 46197a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_NOTES = 15; 462094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana private static final int COLUMN_DELETED = 16; 46211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private static final int COLUMN_SHOULD_SYNC = 17; 4622226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4623226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 4624226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 4625226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = false; 4626226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4627226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String updatedSortOrder = (sortOrder == null) 4628226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ? Groups._ID 4629226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana : (Groups._ID + "," + sortOrder); 4630226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4631b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = provider.mDbHelper.getReadableDatabase(); 4632226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 4633b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(provider.mDbHelper.getGroupView()); 4634226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setProjectionMap(sGroupsProjectionMap); 4635226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (groupIdString != null) { 4636226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups._ID + "=" + groupIdString); 4637226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4638226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountName = uri.getQueryParameter(Groups.ACCOUNT_NAME); 4639226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountType = uri.getQueryParameter(Groups.ACCOUNT_TYPE); 4640226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!TextUtils.isEmpty(accountName)) { 4641226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups.ACCOUNT_NAME + "=" 4642226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4643226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + Groups.ACCOUNT_TYPE + "=" 4644226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 4645226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4646226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 4647226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana null, null, updatedSortOrder); 4648226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToFirst(); 4649226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4650226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4651226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public void close() { 4652226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4653226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("closing when already closed"); 4654226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4655226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = true; 4656226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.close(); 4657226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4658226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4659226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public boolean hasNext() throws RemoteException { 4660226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4661226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 4662226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4663226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4664226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return !mEntityCursor.isAfterLast(); 4665226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4666226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4667038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4668038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4669038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4670038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4671038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4672038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4673e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4674226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public Entity next() throws RemoteException { 4675226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4676226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 4677226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4678226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!hasNext()) { 4679226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 4680226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4681226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4682226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 4683226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4684226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final long groupId = c.getLong(COLUMN_ID); 4685226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4686226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana // we expect the cursor is already at the row we need to read from 4687226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ContentValues groupValues = new ContentValues(); 4688226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 4689226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 4690226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups._ID, groupId); 4691226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 4692226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 4693226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 4694226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 4695226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 4696226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 4697226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 46987a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC1, c.getString(COLUMN_SYNC1)); 46997a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC2, c.getString(COLUMN_SYNC2)); 47007a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC3, c.getString(COLUMN_SYNC3)); 47017a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC4, c.getString(COLUMN_SYNC4)); 47027a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYSTEM_ID, c.getString(COLUMN_SYSTEM_ID)); 470394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana groupValues.put(Groups.DELETED, c.getLong(COLUMN_DELETED)); 47047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.NOTES, c.getString(COLUMN_NOTES)); 47051a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey groupValues.put(Groups.SHOULD_SYNC, c.getString(COLUMN_SHOULD_SYNC)); 4706226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Entity group = new Entity(groupValues); 4707226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4708226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToNext(); 4709226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4710226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return group; 4711226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4712226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4713226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4714a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 47157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 47167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 4717568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 4718568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 47197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 47207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 47215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: 47225ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: 47237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 47245ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (match == RAW_CONTACTS_ID) { 47257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 47267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 47277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 472846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana return new RawContactsEntityIterator(this, uri, contactsIdString, 472946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana selection, selectionArgs, sortOrder); 4730226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS: 4731226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS_ID: 4732226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String idString = null; 4733226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (match == GROUPS_ID) { 4734226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana idString = uri.getPathSegments().get(1); 4735226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4736226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4737226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return new GroupsEntityIterator(this, idString, 4738226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana uri, selection, selectionArgs, sortOrder); 47397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 47407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 47417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 47427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 47437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 47444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 47454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4746a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 47474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4748b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4749b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP: 4750be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 4751b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4752b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4753b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4754f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 4755f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 4756b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4757be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4758b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4759b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4760508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4761b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 476248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 476348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 476448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 476548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 476648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 476748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 476848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 476948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 477048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 477148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 477248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 477348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4774b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4775b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4776b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4777b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4778b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4779b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4780b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4781b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4782c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4783c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4784c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4785c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 478661efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 478761efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 47884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 479125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private void setDisplayName(long rawContactId, String displayName, int bestDisplayNameSource) { 47923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 479325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindString(1, displayName); 47943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 479525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindNull(1); 47963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 479725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(2, bestDisplayNameSource); 479825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(3, rawContactId); 479925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 48003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 48013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 480273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 480373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 480473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 480573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 480673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.bindLong(1, rawContactId); 480773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.execute(); 480873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 480973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4810c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4811c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 4812c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 4813c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4814c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4815c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4816653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 4817c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 4818653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 4819653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 4820c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 4821c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4822c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 4823c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4824c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 4825c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 4826c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4827c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4828c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4829653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 4830c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 4831653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 4832653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 4833c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 4834c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4835ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4836f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 4837f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 4838f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4839f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4840f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4841f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); 4842f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (tokens.length == 0) { 4843f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4844f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4845f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4846f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String address = tokens[0].getAddress(); 4847f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int at = address.indexOf('@'); 4848f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (at != -1) { 4849f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov address = address.substring(0, at); 4850f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4851f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4852f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4853f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 4854f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4855f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4856f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4857f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 4858f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4859f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 4860f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 4861f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4862f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4863f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4864f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4865f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 4866f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4867f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4868a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 4869a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 4870a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 4871a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4872a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 4873a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4874a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 4875a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4876a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 4877a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4878a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4879f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4880f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name) { 4881f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name); 4882f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4883f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4884f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4885f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Returns nickname cluster IDs or null. Maintains cache. 4886f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4887f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4888f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SoftReference<String[]> ref; 4889f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4890f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4891f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (mNicknameClusterCache.containsKey(normalizedName)) { 4892f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = mNicknameClusterCache.get(normalizedName); 4893f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (ref == null) { 4894f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return null; 4895f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4896f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = ref.get(); 4897f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4898f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4899f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4900f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (clusters == null) { 4901f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = loadNicknameClusters(normalizedName); 4902f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = clusters == null ? null : new SoftReference<String[]>(clusters); 4903f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4904f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNicknameClusterCache.put(normalizedName, ref); 4905f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4906f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4907f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4908f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4909f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4910f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] loadNicknameClusters(String normalizedName) { 4911b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 4912f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4913f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupQuery.TABLE, NicknameLookupQuery.COLUMNS, 4914f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.NAME + "=?", new String[] { normalizedName }, 4915f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov null, null, null); 4916f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov try { 4917f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int count = cursor.getCount(); 4918f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (count > 0) { 4919f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = new String[count]; 4920f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov for (int i = 0; i < count; i++) { 4921f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.moveToNext(); 4922f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters[i] = cursor.getString(NicknameLookupQuery.CLUSTER); 4923f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4924f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4925f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } finally { 4926f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.close(); 4927f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4928f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4929f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4930f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4931f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 4932f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4933f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 4934f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 4935f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4936f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4937f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4938f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 4939f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 4940f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 4941f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4942f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4943f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4944f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4945f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return ContactsProvider2.this.getCommonNicknameClusters(normalizedName); 4946f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4947f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4948f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4949f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4950f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 4951f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4952f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 4953f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 1, rawContactId); 4954f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 2, dataId); 4955f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 3, lookupType); 4956f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 4, name); 4957f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 4958f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4959f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4960f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4961f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 4962f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4963f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 4964f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupDelete, 1, dataId); 4965f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 4966f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4967f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 49682d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 4969d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4970d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 4971d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4972d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 4973d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 4974d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 4975d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 4976e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 4977d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN(" 4978d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 4979d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 4980d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NICKNAME + "," 4981d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.ORGANIZATION + "))"); 4982e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 4983e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 49845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 4985c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4986c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 4987c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 4988c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4989c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4990a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 4991c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit) { 499220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), limit, 499320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov true); 49945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 49955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 49965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 499720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String limit, boolean allowEmailMatch) { 4998d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4999d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + NameLookupColumns.RAW_CONTACT_ID + 5000d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5001d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 5002d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 50035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 5004a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 5005a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 5006a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 500720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov + NameLookupType.ORGANIZATION); 500820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 500920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 501020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 501120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append(")"); 50123de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 5013c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limit != null) { 5014c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(" LIMIT ").append(limit); 5015c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5016c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(")"); 5017ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5018ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 50194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 50204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 50214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 50224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 5023b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 5024b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 5025b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 5026b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 5027b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 50284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 50294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 5030b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 5031b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5032b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5033caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 50345e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 50355e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 50365e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 50375e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 50385e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 50395e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 50405e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 50415e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 50425e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 50435e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 50445e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5045caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 5046caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 5047caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 5048df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 5049df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 5050caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 5051caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 5052caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5053caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 50546f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 5055caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 50566f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 5057caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5058627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 5059627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov protected boolean isWritableAccount(Account account) { 5060627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 5061627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 5062627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 5063627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 5064627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov account.type.equals(sync.accountType)) { 5065627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov return sync.supportsUploading(); 5066627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5067627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5068627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 5069627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 5070627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5071627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 5072627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov return false; 5073627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 50744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 5075