ContactsProvider2.java revision 82bd858c9911dfbd8dca52dc276333768b0a429e
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; 213de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.AggregatedPresenceColumns; 223de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.AggregationExceptionColumns; 233de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.Clauses; 243de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.ContactsColumns; 253de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.DataColumns; 263de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.DisplayNameSources; 273de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.GroupsColumns; 283de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.MimetypesColumns; 293de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.NameLookupColumns; 303de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.NameLookupType; 31f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.NicknameLookupColumns; 323de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.PhoneColumns; 333de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.PhoneLookupColumns; 343de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.PresenceColumns; 353de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.RawContactsColumns; 363de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.SettingsColumns; 37a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.StatusUpdatesColumns; 383de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.Tables; 39a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Lists; 40a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Maps; 41a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Sets; 423de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 43b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 44caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 4570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wongimport android.accounts.OnAccountsUpdatedListener; 46c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 47568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 48568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 4935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 5235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.Entity; 5367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.EntityIterator; 54568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 553d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 5667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 573de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.content.SharedPreferences.Editor; 58b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 60ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 61a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 62b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 63b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 66c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 68d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 69b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 700e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 71d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 723d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 73508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 743de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 753de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.LiveFolders; 763de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.OpenableColumns; 773de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.SyncStateContract; 78b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 793de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 803de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 813de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 823de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 833de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 843de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 8582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 87ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 88ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 92de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 93b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 944097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 9567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 96a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 97a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 98f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Token; 99f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer; 100c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 102d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 103b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 104d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 105d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 106f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport java.lang.ref.SoftReference; 1077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 109b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1100e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 112622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 113b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1140e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 115ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 12170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wongpublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdatedListener { 122caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 123bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 124bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 125bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 127619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 128619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 129619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1333d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1343d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1353d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1410e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1420e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 143a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 145d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 146d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.TIMES_CONTACTED + " DESC, " 1479b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 148d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 149d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 150d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 151d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 152d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 1624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 1664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1676bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1686bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 169ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 17048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 17148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 17248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 17348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 17448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 17548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 17648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 17748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 178a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1796bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1806bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 181b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 182b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 183b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 18482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 18582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 1861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 18731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 18831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 189eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 190eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 191ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 192ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 193ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 194ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 19535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 196b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 19735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 198c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 199c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 200c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2011b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2021b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2031b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2041b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2051b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 20667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private interface ContactsQuery { 2075ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final String TABLE = Tables.RAW_CONTACTS; 2089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 20967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2106cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2116cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 2126cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 213ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 214ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 21667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_NAME = 1; 21767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_TYPE = 2; 21867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 21967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 220d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 221d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final String TABLE = Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS; 22267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 22367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2246cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 226d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.CONCRETE_ID, 2273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.CONCRETE_ID, 228ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 229ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 230d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 23167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 232d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 23367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int MIMETYPE_ID = 3; 234ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2351f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private interface DisplayNameQuery { 23767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final String[] COLUMNS = new String[] { 2403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 242f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 243a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka Organization.TITLE, 2443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 0; 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 1; 248a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public static final int DATA = 2; 249a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public static final int TITLE = 3; 2503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 25214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 25367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 25588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 260f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 26188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 26288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 26388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 26488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 26588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 26688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 26788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 268f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 2693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 27114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 275f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 2763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 27814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 279321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 28020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 28120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 282321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 283321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 28420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 28520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 286f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 287f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private interface NicknameLookupQuery { 288f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 289f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 290f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] COLUMNS = new String[] { 291f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.CLUSTER 292f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov }; 293f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 294f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int CLUSTER = 0; 295f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 296f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 29719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 29819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 29919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 30019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 30119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.DELETED 30219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 30319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 30419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 30519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 30619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 30725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private static final HashMap<String, Integer> sDisplayNameSources; 3083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov static { 30925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources = new HashMap<String, Integer>(); 31025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(StructuredName.CONTENT_ITEM_TYPE, 31125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.STRUCTURED_NAME); 312a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sDisplayNameSources.put(Nickname.CONTENT_ITEM_TYPE, 313a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka DisplayNameSources.NICKNAME); 31425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Organization.CONTENT_ITEM_TYPE, 31525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.ORGANIZATION); 31625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Phone.CONTENT_ITEM_TYPE, 31725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.PHONE); 31825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Email.CONTENT_ITEM_TYPE, 31925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.EMAIL); 3203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 32131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 322caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov public static final String DEFAULT_ACCOUNT_TYPE = "com.google.GAIA"; 323df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 324caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 32571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 32671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 32771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 32871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 32971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 33071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 33171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 33271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 33371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 33471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 33571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 33671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 33771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 33871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 339038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 340038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 341e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 343ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 344d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 3454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 350e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 351ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 352ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 353ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 354ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 355373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 356b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 357eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 358eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 35982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 36082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 3611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 364c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 365c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 367c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 368d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Precompiled sql statement for incrementing times contacted for an contact */ 369f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private SQLiteStatement mLastTimeContactedUpdate; 3703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 37125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 37273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** Precompiled sql statement for marking a raw contact as dirty */ 37373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private SQLiteStatement mRawContactDirtyUpdate; 37482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 375a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 376f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 377f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 378a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 379a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 380a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 381a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 382a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 3834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 3844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 385a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 386d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 387d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 388d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 3893653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 3903653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 3912d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 3922d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 3933653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 3945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 3955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 3965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 3975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 398ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 399ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 4005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 4013653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4045ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 405b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 408ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 40948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 411ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 41348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 417ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 41848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 420ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 421ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 422ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 423ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 42435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 425b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 426b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 42735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 428a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 429b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 430b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 431b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 432b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 434eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 435eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 43682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 43782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 4381f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 439c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 440c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 441c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 442c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 443c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 444c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 445c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4461b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4471b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4481b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 4501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 4511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 4521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 4531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 45419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 45519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 45619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 457038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 458038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 459e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 4614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 4624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 4634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 469f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 4704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 472d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey sContactsProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 473d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 474d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey sContactsProjectionMap.put(OpenableColumns.SIZE, "0 AS " + OpenableColumns.SIZE); 47582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sContactsProjectionMap.put(Contacts.CONTACT_PRESENCE, 47682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE 47782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + " AS " + Contacts.CONTACT_PRESENCE); 47882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sContactsProjectionMap.put(Contacts.CONTACT_STATUS, 479a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov StatusUpdatesColumns.STATUS 48082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + " AS " + Contacts.CONTACT_STATUS); 48182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sContactsProjectionMap.put(Contacts.CONTACT_STATUS_TIMESTAMP, 482a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov StatusUpdatesColumns.TIMESTAMP 48382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + " AS " + Contacts.CONTACT_STATUS_TIMESTAMP); 4844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 4864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 4874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 4884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 4894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 4904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 4914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 4924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 4934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 4944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 4954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 4964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 4974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 4984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 4994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 5004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 5014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 5024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 5034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 5044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 5052815f58f72f109790585931f601a63ddc02536a5Evan Millar 5064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 5074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 5084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 5094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 5154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 5164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 5174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 5184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 5194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 5204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 5214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 5224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 5234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 5244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 5254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 5264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 5274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 5284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 5294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 53382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 5344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 53956d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 54782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Contacts.CONTACT_PRESENCE, 54882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StatusUpdates.PRESENCE + " AS " + Contacts.CONTACT_PRESENCE); 54982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Contacts.CONTACT_STATUS, 55082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StatusUpdatesColumns.STATUS + " AS " + Contacts.CONTACT_STATUS); 55182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Contacts.CONTACT_STATUS_TIMESTAMP, 55282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StatusUpdatesColumns.TIMESTAMP + " AS " + Contacts.CONTACT_STATUS_TIMESTAMP); 5534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 554a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 5565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 5575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 5585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 5595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 5655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 5665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 5675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 5685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 5695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 5705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 5715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 5725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 5735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 5745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 5755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 5765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 5775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 5785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 5795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 5835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5848f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 59282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CONTACT_PRESENCE, 59382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StatusUpdates.PRESENCE + " AS " + Contacts.CONTACT_PRESENCE); 59482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CONTACT_STATUS, 59582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StatusUpdatesColumns.STATUS + " AS " + Contacts.CONTACT_STATUS); 59682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CONTACT_STATUS_TIMESTAMP, 59782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StatusUpdatesColumns.TIMESTAMP + " AS " + Contacts.CONTACT_STATUS_TIMESTAMP); 5985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 5995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 6005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 601e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 602e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 603e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_ID + " AS " + PhoneLookup._ID); 60456d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 60556d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar Contacts.LOOKUP_KEY + " AS " + PhoneLookup.LOOKUP_KEY); 606e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 607e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + PhoneLookup.DISPLAY_NAME); 608e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 609e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 610e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 611e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 612e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " + PhoneLookup.TIMES_CONTACTED); 613e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 614e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_STARRED + " AS " + PhoneLookup.STARRED); 615e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 616e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 617e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 618e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.PHOTO_ID + " AS " + PhoneLookup.PHOTO_ID); 619e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 620e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " + PhoneLookup.CUSTOM_RINGTONE); 621e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 622e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.HAS_PHONE_NUMBER + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 623e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 624e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 625e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 626e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 627e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 628e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 629e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 630e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 631e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 6329261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 633e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov HashMap<String, String> columns; 6347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 635ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 636ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 63789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 638035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 639035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 6409261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 6419261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 6429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 64389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 644ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 64567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 646ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 6473cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 64894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 6493cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 65038446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 65189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 65289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 65389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 65489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 655ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 656ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 6576cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 658ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 659ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 660d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 661d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 662ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 663ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 664ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 665d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 666d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 667ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 668f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 669ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 670ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 671b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 672b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 673b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 674b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 6750c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 6760c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 677b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 678b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 679eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 680eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 681eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 682eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 683eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 684eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 685341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 686341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 687341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 688fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 689341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 690341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 691341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 69268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 69368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 69468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 69568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 69668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 697e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 69868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 69968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 70068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 701eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 702eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 703373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 7044dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 70582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, StatusUpdates.DATA_ID); 70682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 70782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 70882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 70970c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 71070c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 71182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 71282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 71382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 71482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 71582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.STATUS, 71682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StatusUpdatesColumns.STATUS + " AS " + StatusUpdates.STATUS); 71782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, 71882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StatusUpdatesColumns.TIMESTAMP + " AS " + StatusUpdates.STATUS_TIMESTAMP); 71982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 72019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 7211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 7221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 7231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 7241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 7251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 7261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 7271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 7281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 7291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 7301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 7311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 7324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 7334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 7343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 7353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 7363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 7373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 7383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 740653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 7413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 7433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 744a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 745a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 746a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 747a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 748a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 749a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 750a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 751a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 7523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 754653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 755653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 756653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mMimetypeId = mOpenHelper.getMimeTypeId(mMimetype); 757653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 758653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 759653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 760653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 7613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 7623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 7633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 7645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 765e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 766e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 767e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 768e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 769653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 770e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 771e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 772e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 7733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 7763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 7773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 7783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 779653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 780f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 78114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 78214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 783653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 784653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 785653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 786653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 787653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 788653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 789653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 790653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 791653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 792653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 793653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 794653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 795653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 796653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 797653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 798653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 799653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 800653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " = " + dataId, null); 801653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 802653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 803f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 804653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 805653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 8063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 80914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 81014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 81114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 8123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 8133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 8145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 8153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 8173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 8205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long newPrimaryId = findNewPrimaryDataId(db, rawContactId); 8213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (newPrimaryId != -1) { 82214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov setIsPrimary(rawContactId, newPrimaryId, getMimeTypeId()); 8233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected long findNewPrimaryDataId(SQLiteDatabase db, long rawContactId) { 827e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 828e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 8295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Cursor c = queryData(db, rawContactId); 8303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 831e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 83214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 833f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 834e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 835e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 836e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 837e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 8383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 8403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 8413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 842e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return primaryId; 843e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 844e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 845e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 846e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 847e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 848e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 849e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 850e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 8513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected Cursor queryData(SQLiteDatabase db, long rawContactId) { 85414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return db.query(DataDeleteQuery.TABLE, DataDeleteQuery.CONCRETE_COLUMNS, 85514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId + 85614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " AND " + MimetypesColumns.MIMETYPE + "='" + mMimetype + "'", 8573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov null, null, null, null); 8583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 86025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 8613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String bestDisplayName = null; 86225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 86325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov 86467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Cursor c = db.query(DisplayNameQuery.TABLE, DisplayNameQuery.COLUMNS, 8655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId, null, null, null, null); 8663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 8673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov while (c.moveToNext()) { 8683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String mimeType = c.getString(DisplayNameQuery.MIMETYPE); 869a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 870a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // Display name is at DATA1 in all type. This is ensured in the constructor. 871a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String name = c.getString(DisplayNameQuery.DATA); 872a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (TextUtils.isEmpty(name) 873a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka && Organization.CONTENT_ITEM_TYPE.equals(mimeType)) { 874a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka name = c.getString(DisplayNameQuery.TITLE); 8753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 876a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka boolean primary = StructuredName.CONTENT_ITEM_TYPE.equals(mimeType) 877a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || (c.getInt(DisplayNameQuery.IS_PRIMARY) != 0); 8783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 87901911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (name != null) { 88025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov Integer source = sDisplayNameSources.get(mimeType); 88101911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (source != null 88201911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov && (source > bestDisplayNameSource 88301911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov || (source == bestDisplayNameSource && primary))) { 88425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov bestDisplayNameSource = source; 8853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov bestDisplayName = name; 8863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 8913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 8923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 89425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov setDisplayName(rawContactId, bestDisplayName, bestDisplayNameSource); 895285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 896285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateDisplayName(db, rawContactId); 897285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 8983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 899a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 900a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 901a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return true; 902a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 903622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 904622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 905622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 906622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * as baseline, but augmented with any updates. 907622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 908622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 909622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 910622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 911622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=" + dataId, 912622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey null, null, null, null); 913622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 914622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 915622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 916622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 917622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.put(key, cursor.getString(i)); 918622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 919622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 920622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 921622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 922622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 923622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 924622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 925622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 9263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 9293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 9313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 9323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 936622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 9373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 938622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 9393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 940622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 9413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 9445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 945622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 94614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 94714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 94814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 949f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 950f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 95125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 95214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 95314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 95414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 95514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 95614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 957f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 958622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 959622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 960cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 961622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 962622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 96314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 964f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 96514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 966f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 967f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 968f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 969f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 97014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 97125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 97214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 97314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 97414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 97514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 97614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 97714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 97814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 97914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 98014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 981f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 98225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 98314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 9843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 987622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 9883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 989622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 990622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 991622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 992622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 9933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 994622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 995622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 996622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 997622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 998622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 999622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1000622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 1001622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1002622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1003622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 1004622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1005622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1006622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 10078c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1008622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1009622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 1010622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } else if (!touchedUnstruct && touchedStruct) { 10118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1012622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 1013622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(name); 1014622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 1015622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1016622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1017622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1018622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1019622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1020622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1021622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1022622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1023622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1024622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1025622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1026622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1027622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1028622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1029622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1030622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1031622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1032622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1033622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1034622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1035f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1036622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1037622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1038622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1039f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1040622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1041622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1042622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1043622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1044622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1045622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1046622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1047622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1048622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1049622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1050622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1051622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1052622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1053622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1054622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1055622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1056622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1057622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 1058622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 1059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1060622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 1061622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1062622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1063622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1064622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1065622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1066622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1067622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 1068622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } else if (!touchedUnstruct && touchedStruct) { 1069622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1070622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1071622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 10723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 10773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 10793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 10803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 10823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 10843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 10853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 10885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1089622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1090622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1091622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1093622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1094622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1095f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1096622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1097622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1098622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1099f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1100622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1102622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1103622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1104622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1105622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1106622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1107622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1108622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1109622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 11103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1111622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1112622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1113622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1114622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1115622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 11203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 11223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 11233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1127a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1128a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1129a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1130a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1131a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 113225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1133a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1134a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 11353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 113814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1139f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1140a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1141a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1142a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 114314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 114414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1145f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 114614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 114725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1148a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 1149a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 115014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 115114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 115214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 115314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1154a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 115514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 115614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 115714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 115825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1159a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 116014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 116114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 116214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 116314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 11643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 11653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 11663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 11673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 11683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 11693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 11703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1172a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1173a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1174a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1175a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1176a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 11773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1179e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1180e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1181e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1182e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1183e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1184e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1185e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 11865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 118714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 118814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 118914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 119014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 119125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1192f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 119314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 119414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 119514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 119614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 119714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1198f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 119914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 120014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 120114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 120214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1203f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 120414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1205f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1206f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 120725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 120814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 120914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 121014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 121114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 121214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 121314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 121414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 121514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 121614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1217f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 121825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 121914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1220e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1221e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1222e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1223e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1224e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1225e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1226e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1227e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1228e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1229e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1230e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1231e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1232e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1233e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 123414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 123514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 123614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 123714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 123814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 123914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 124014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 124114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 124214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 124314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 124414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 124514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 124625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1247f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 124814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 124914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 125014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 125114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 125214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1253f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 125414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 125514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 125614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 125714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1258f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 125914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1260f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1261f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 126225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 126314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 126414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 126514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 126614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 126714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 126814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 126914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 127014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 127114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1272f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 127325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 127414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 127514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 127614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 127714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 12783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 12793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 12813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 12823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 12860b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 12870b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 12880b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 12890b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1290653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 12910b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1292653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 12930b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1294285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 129525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 12960b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 12970b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 12980b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1299653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1300653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1301653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1302653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1303653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1304f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 130514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 130614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 13070b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 13080b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 13090b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1310653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1311f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1312653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 13130b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1314285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 131525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 13160b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 1317f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 13180b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 131914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 132014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 132114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 132214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 132314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 132414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 132514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 132614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 132714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 132814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1329285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 133025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 133114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1332653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1333653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1334653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1335e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1336e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1337e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1338e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1339653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1340653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1341653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1342e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1343653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1344653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1345e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1346653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 13475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1348653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1349e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 1350653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1351653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1352653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=" + dataId, null); 1353e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 13543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 13583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 13593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 13603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 13613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 13623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 13633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 13643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 13653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 13663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 13673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 13683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1372653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1373653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1374653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1375653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1376653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1377653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1378653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1379653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1380653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 13810be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 13820be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 13830be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1384653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1385653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1386653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1387653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1388f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 138914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1390653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1391f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 13920be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 13930be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 13940be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 13950be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 13960be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 13970be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 13980be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 13990be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 14000be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 14010be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 14020be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 14030be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 14040be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 14050be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 14060be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov mOpenHelper.updateContactVisible(contactId); 14070be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1408653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1409653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1410653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1411653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1412653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1413653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1414653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1415653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1416653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1417653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1418653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1419653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1420653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1421653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1422653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1423653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1424653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1425653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1426653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1427653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1428653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1429653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1430653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1431653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1432653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId); 1433653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1434653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1435653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1436653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1437a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1438a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1439a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1440a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1441a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1442653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1443653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1444a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1445a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1446a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1447a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1448a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1449a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1450a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1451a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1452a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1453285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1454285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1455285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1456a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1457a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1458a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1459a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1460a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1461f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1462a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1463f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1464a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1465a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1466a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1467a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1468a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1469a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1470a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1471a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1472a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1473a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1474a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1475a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1476a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1477a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1478a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1479a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1480a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1481a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 14823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 148353056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 14844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private OpenHelper mOpenHelper; 148531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 14864097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1487f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1488f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private HashMap<String, SoftReference<String[]>> mNicknameClusterCache = 1489f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov new HashMap<String, SoftReference<String[]>>(); 1490622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1491622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1492622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1493f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1494a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1495a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 149620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 149720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1498ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 149973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private boolean mImportMode; 150073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1501b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mInsertedRawContacts = Sets.newHashSet(); 1502b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1503b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1504de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 15051a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 15061a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 150781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 150881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 1509a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 151053056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 1511a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1512a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1513a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1514a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 1515a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 151653056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 151753056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 1518a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 15194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 15204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 15214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1522de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 152335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1524de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1525de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mOpenHelper = (OpenHelper)getOpenHelper(); 1526a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1527a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mOpenHelper, this, mGlobalSearchSupport); 1528cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov mContactAggregator = new ContactAggregator(this, mOpenHelper, mAggregationScheduler); 15290e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1530a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1531d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 1532653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1533c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1534653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1535653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1536653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1537653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1538653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1539c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1540653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1541653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1542653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1543653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1544653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1545653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1546653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1547653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1548653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1549653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1550653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 15515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mLastTimeContactedUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 15526cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.TIMES_CONTACTED + "=" + RawContacts.TIMES_CONTACTED + "+1," 1553d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + RawContacts.LAST_TIME_CONTACTED + "=? WHERE " + RawContacts.CONTACT_ID + "=?"); 1554a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 155525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate = db.compileStatement( 155625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 155725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " SET " + RawContactsColumns.DISPLAY_NAME + "=?," 155825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov + RawContactsColumns.DISPLAY_NAME_SOURCE + "=?" + 155925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 15603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 156173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 156273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + RawContacts.DIRTY + "=1 WHERE " + RawContacts._ID + "=?"); 156373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1564a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate = db.compileStatement( 1565a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.CONTACTS 1566a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1567a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1568a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1569a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1570a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1571a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1572a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1573a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1574a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1575a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 1576a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ORDER BY " + StatusUpdatesColumns.TIMESTAMP + " DESC" + 1577a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LIMIT 1)" 1578a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1579e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1580622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Locale locale = Locale.getDefault(); 158128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 158228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 158328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 158428f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 1585622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey context.getString(com.android.internal.R.string.common_name_conjunctions), 1586622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey locale); 1587f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 1588622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mPostalSplitter = new PostalSplitter(locale); 15894097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1590f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1591f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1592f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1593f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1594f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1595f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1596f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1597a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert = db.compileStatement( 1598a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1599a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 1600a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.TIMESTAMP + "," 1601a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.STATUS + ")" + 1602a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " VALUES (?,?,?)"); 1603a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1604a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace = db.compileStatement( 1605a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1606a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 1607a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.TIMESTAMP + "," 1608a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.STATUS + ")" + 1609a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " VALUES (?,?,?)"); 1610a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1611a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp = db.compileStatement( 1612a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 1613a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " SET " + StatusUpdatesColumns.TIMESTAMP + "=?," 1614a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.STATUS + "=?" + 1615a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 1616a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + " AND " + StatusUpdatesColumns.STATUS + "!=?"); 1617a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1618a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete = db.compileStatement( 1619a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1620a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1621a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 16223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 16233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1624e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 16253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 16263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 162767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 162867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 16293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 16303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 163114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 16323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 16333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1634622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1635622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1636a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1637a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 16383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 16393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1640568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 16413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1642568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1643c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov verifyAccounts(); 164470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 16451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 16464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 16474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1648c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 1649c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1650c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1651c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 1652c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 165331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1654de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 165531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov protected OpenHelper getOpenHelper(final Context context) { 165631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov return OpenHelper.getInstance(context); 165731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 165831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1659285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov /* package */ ContactAggregationScheduler getContactAggregationScheduler() { 1660285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mAggregationScheduler; 1661285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1662285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1663013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1664013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1665013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1666013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 16673d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 16683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 16693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 16703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 16713d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1672568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1673568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1674568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1675568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1676568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1677568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1678568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1679568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1680568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1681ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1682568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1683568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1684568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1685568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1686568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1687568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1688568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1689568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1690568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1691568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1692ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1693ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1694568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov scheduleContactAggregation(); 1695568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1696568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1697568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1698568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1699568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1700568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1701568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 17023d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1703568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1704568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 17053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 17063d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 17073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 17083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 17093d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 17103d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 17113d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 17123d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 17133d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 17143d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 17153d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1716568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 17170e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 17183d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 171973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = true; 17203d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 17213d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 17220e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(aggregatorEnabled); 17233d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 17243d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 17253d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 17263d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 172773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } finally { 172873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = false; 17293d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 17303d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 17313d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1732a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1733a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 1734a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 1735a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 1736a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1737a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1738a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 1739a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1740a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1741a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1742a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1743a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1744a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1745a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mOpenHelper.wipeData(); 1746a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1747a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1748568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1749568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 1750568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1751568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1752568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1753568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1754568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1755568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 1756ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 1757ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 1758ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 1759ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 1760ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 1761ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1762ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 1763ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 176481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 1765ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1766ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1767568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1768568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1769568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1770568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1771568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1772568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1773568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1774568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1775568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1776568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1777568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1778568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1779568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1780568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1781568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1782568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1783568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 1784568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1785568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1786568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1787568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1788568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1789568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1790568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 1791568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1792568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1793568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1794568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 17954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1796285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1797bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1798b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1799b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1800285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 18011ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1802b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1803b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1804b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1805b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 1806285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 1807b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 1808df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 1809285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1810285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1811285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1812285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 1813bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1814b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1815b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1816285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1817b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 18181ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 18191a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 18201a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 18211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mOpenHelper.updateAllVisible(); 18221a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 1823b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1824b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1825b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1826bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1827b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1828b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1829b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long rawContactId : mInsertedRawContacts) { 1830b5a4add17815167d20a90645779df34cdf45280dFred Quintana mContactAggregator.insertContact(mDb, rawContactId); 1831285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1832b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1833b5a4add17815167d20a90645779df34cdf45280dFred Quintana String ids; 1834b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 1835b5a4add17815167d20a90645779df34cdf45280dFred Quintana ids = buildIdsString(mUpdatedRawContacts); 1836b5a4add17815167d20a90645779df34cdf45280dFred Quintana mDb.execSQL("UPDATE raw_contacts SET version = version + 1 WHERE _id in " + ids, 1837b5a4add17815167d20a90645779df34cdf45280dFred Quintana new Object[]{}); 1838b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1839b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1840b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 1841b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 1842b5a4add17815167d20a90645779df34cdf45280dFred Quintana mOpenHelper.getSyncState().update(mDb, id, entry.getValue()); 1843b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1844b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1845b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1846b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1847b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1848b5a4add17815167d20a90645779df34cdf45280dFred Quintana private String buildIdsString(HashSet<Long> ids) { 1849b5a4add17815167d20a90645779df34cdf45280dFred Quintana StringBuilder idsBuilder = null; 1850b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 1851b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (idsBuilder == null) { 1852b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder = new StringBuilder(); 1853b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append("("); 1854b5a4add17815167d20a90645779df34cdf45280dFred Quintana } else { 1855b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(","); 1856b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1857b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(id); 1858b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1859b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(")"); 1860b5a4add17815167d20a90645779df34cdf45280dFred Quintana return idsBuilder.toString(); 1861285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1862285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1863285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1864cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 186581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 186681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 186781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 186881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 186981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 187081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 187181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 1872cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 1873568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1874568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected void scheduleContactAggregation() { 1875dee54bb86f3608730f0b9f37d8982a7f6b280a85Dmitri Plotnikov mContactAggregator.schedule(); 1876568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1877568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1878285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 1879285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mInsertedRawContacts.contains(rawContactId); 1880285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1881285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 18823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 18833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 18843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 18853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 18863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 18873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 18883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 18893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 18903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 18914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1892de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 1893bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1894b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "insertInTransaction: " + uri); 1895b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1896f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1897f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 1898f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 1899f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1900a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 1901a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 190235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1903a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 190435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 1905de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov id = mOpenHelper.getSyncState().insert(mDb, values); 190635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 190735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1908d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1909d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 19106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 19116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 19126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 19135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 1914f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 1915d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov id = insertRawContact(values, account); 1916f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1917a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1918a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1919a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 19205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 19215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 1922f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1923f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1924a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1925a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1926a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1927a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 1928f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1929f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1930a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1931a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1932a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1933ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1934ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 19355aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertGroup(uri, values, account, callerIsSyncAdapter); 1936f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1937ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1938ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1939ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1940eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 19415aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 194243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 1943eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 1944eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 1945eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 194682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 194782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 19481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 19491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 19501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1951a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 195281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 1953f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 1954a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1955a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 19567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 19577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 19587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 19597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1960de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 1961a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1962a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1963a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1964035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 1965035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 1966035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 1967035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 1968035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 19697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 1970035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 1971035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 19726cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME); 19736cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 1974035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 1975035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 1976035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 1977035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 1978035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1979035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 1980035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1981035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 1982df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_NAME, account.name); 1983df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_TYPE, account.type); 1984035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1985035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 19867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 19877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 19887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 1989d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 19906bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 19916bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 19926bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 19936bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1994d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 1995de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 19966bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 19976bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 19986bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 1999a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2000a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2001a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2002f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 2003a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2004a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2005d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertRawContact(ContentValues values, Account account) { 2006a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 2007d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov overriddenValues.putNull(RawContacts.CONTACT_ID); 2008f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 20097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 20107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 20117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 20123d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 20133d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 20143d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov overriddenValues.put(RawContacts.AGGREGATION_MODE, 20153d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DISABLED); 20163d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 20173d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2018023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov long rawContactId = 2019023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, overriddenValues); 2020023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 2021285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2022285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2023285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.add(rawContactId); 2024023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2025a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2026a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2027a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2028a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2029a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2030a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2031a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2032a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2033f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2034a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2035de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2036de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 203767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2038de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 203920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2040de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2041de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2042de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2043de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 2044de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2045de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2046508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2047de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2048de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2049de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2050de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2051de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 20524097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2053de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mOpenHelper.getMimeTypeId(mimeType)); 2054de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2055a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2056a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2057a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2058f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2059de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2060a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2061b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2062a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2063a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2064a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2065a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2066a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 20674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 20684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 20698e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 20708e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 20718e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 20728e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 20738e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 20748e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov int aggregationMode = mOpenHelper.getAggregationMode(rawContactId); 2075f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 20768e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 20778e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 20788e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 20798e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2080421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 2081f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 20828e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 20838e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 20848e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 20858e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 2086f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 20878e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 20888e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 20898e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2090f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 20918e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2092f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2093c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 20948e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 20958e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2096f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 20978e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2098f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2099f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2100f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2101a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 21025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 21039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 21049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 21055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 21069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 21079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 21089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 21099261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 21109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 21115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId) { 21129261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Account account = null; 21136cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts._ID + "=" 21145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId, null, null, null, null); 21159261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 21169261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 211767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountName = c.getString(ContactsQuery.ACCOUNT_NAME); 211867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountType = c.getString(ContactsQuery.ACCOUNT_TYPE); 21199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 21209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana account = new Account(accountName, accountType); 21219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 21249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 21259261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21269261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 21279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 21289261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "has a sourceid the the contact must be associate with " 21299261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 21309261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21319261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 21329261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 21335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 21346cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 21359261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2136df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 21379261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 21389261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 21399261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return c.getLong(0); 21409261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 21419261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2142df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2143df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 21449261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 21459261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 21469261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 21479261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 21489261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 21499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return groupId; 21519261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 21539261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 21549261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21559261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 21569261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 21579261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 215820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 215920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2160f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 216120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 216220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2163de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2164de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 216514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2166de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2167de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 216814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 216914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2170a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2171a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2172f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 217388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 2174a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2175a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2176a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 217788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 217820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 217920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2180de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 218120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 218220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 218320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 218420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 218520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 218688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 218788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 218888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 218920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2190f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 219188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 219288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 219314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=" + dataId, null, 219414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov null); 2195f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 219620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 219720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 219820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 219920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 220020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 220114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 220220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 220320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 220420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 220520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 220620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 220720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 220820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 220920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 221020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 22117a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 221220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 221320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 221420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2215a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2216a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 22178e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2218a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2219a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2220a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 22218e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 222220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 222320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 222420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 222520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 222620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 222720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2228ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2229ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 22305aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertGroup(Uri uri, ContentValues values, Account account, boolean callerIsSyncAdapter) { 2231ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 2232ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 2233ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 2234ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2235ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2236ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 223767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.RES_PACKAGE); 223867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 223967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.put(GroupsColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 224067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 224167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.remove(Groups.RES_PACKAGE); 2242ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2243f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 224473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov overriddenValues.put(Groups.DIRTY, 1); 224573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 224673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2247ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey long result = mDb.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 2248ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 22491a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (overriddenValues.containsKey(Groups.GROUP_VISIBLE)) { 22501a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2251ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2252ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2253ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2254ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2255ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 22565aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2257e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 22585aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 22591a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 22601a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2261e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 22621a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 2263e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2264e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2265e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2266ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 226782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 22681f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 226982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 227082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 227182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (TextUtils.isEmpty(handle) || !values.containsKey(StatusUpdates.PROTOCOL)) { 22724dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 22734dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 22744dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 227582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final long protocol = values.getAsLong(StatusUpdates.PROTOCOL); 22764dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 22774dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 22784dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (protocol == Im.PROTOCOL_CUSTOM) { 227982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 22804dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 22814dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 22824dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 22834dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 22841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 22851f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2286dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 2287dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 228882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 228970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov StringBuilder selection = new StringBuilder(); 22901f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String[] selectionArgs; 2291dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2292dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 2293dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 2294dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2295dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selection.append(Tables.DATA + "." + Data._ID + "="); 2296dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selection.append(dataId); 2297dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selectionArgs = null; 22981f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 2299dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 2300dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2301dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 2302dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 2303dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2304dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 2305dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selection.append( 2306dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton "((" + MimetypesColumns.MIMETYPE + "='" + Im.CONTENT_ITEM_TYPE + "'" 2307dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton + " AND " + Im.PROTOCOL + "=?" 2308dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton + " AND " + Im.DATA + "=?"); 2309dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2310dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selection.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2311dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton DatabaseUtils.appendEscapedSQLString(selection, customProtocol); 2312dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2313dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selection.append(") OR (" 2314dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton + MimetypesColumns.MIMETYPE + "='" + Email.CONTENT_ITEM_TYPE + "'" 2315dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton + " AND " + Email.DATA + "=?" 2316dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton + "))"); 2317dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selectionArgs = new String[] { String.valueOf(protocol), handle, handle }; 2318dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 2319dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selection.append( 2320dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton MimetypesColumns.MIMETYPE + "='" + Im.CONTENT_ITEM_TYPE + "'" 2321dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton + " AND " + Im.PROTOCOL + "=?" 2322dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton + " AND " + Im.DATA + "=?"); 2323dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 2324dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selection.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 2325dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton DatabaseUtils.appendEscapedSQLString(selection, customProtocol); 2326dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 23274dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 2328dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selectionArgs = new String[] { String.valueOf(protocol), handle }; 2329dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 23301f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 233182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 2332dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton selection.append(" AND " + DataColumns.CONCRETE_ID + "=") 233382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov .append(values.getAsLong(StatusUpdates.DATA_ID)); 2334dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 233570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 233600ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey selection.append(" AND ").append(getContactsRestrictions()); 233770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 23381f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 23391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2340de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 234170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.toString(), selectionArgs, null, null, null); 23421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 234367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 23445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2345e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 23461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 23471f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 23481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 23491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 23501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 235131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 235231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 235331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 23541f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 23551f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 235682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2357a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2358a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2359a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2360a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2361a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2362a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2363a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 236482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2365a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2366a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 236782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 236882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 236982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 237082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 237182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2372a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 237382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 237482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 23751f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2376a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2377a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2378a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2379e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 238082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 238182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 2382a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 2383a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 2384a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 238582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 238682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 2387a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 2388a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 2389a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindString(3, status); 2390a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 2391a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 2392a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov long timestamp = System.currentTimeMillis(); 2393a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2394a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 2395a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 2396a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(2, timestamp); 2397a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindString(3, status); 2398a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 2399a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 2400a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 2401a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 2402a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindString(2, status); 2403a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 2404a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindString(4, status); 2405a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 2406a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2407e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2408e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2409bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2410a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2411a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 2412a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 2413a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 2414a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2415a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2416a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 24171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24181f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 24194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2420de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2421bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2422b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2423b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2424b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2425f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2426f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2427508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2428508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 242935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2430de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mOpenHelper.getSyncState().delete(mDb, selection, selectionArgs); 243135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2432b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2433b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2434b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2435b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2436b5a4add17815167d20a90645779df34cdf45280dFred Quintana return mOpenHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2437b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2438cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2439cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2440cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2441cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2442cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2443d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2444d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2445cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 24466bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 24476bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 24482e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 24492e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 24502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 24512e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 24522e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 24532e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 24542e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 24552e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 24562e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 24572e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 24582e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 24592e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 24602971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 24612971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 24622971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2463e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 24642971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 24652971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 24662971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2467f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana numDeletes += deleteRawContact(rawContactId, callerIsSyncAdapter); 24682971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 24692971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 24702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 24712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 24722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 24732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 24742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 24755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 24762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2477f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteRawContact(rawContactId, callerIsSyncAdapter); 2478508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2479508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 248020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2481f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2482944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2483f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 248420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 248520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 248648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 248748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 248848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 248948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2490508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2491f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2492f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteData(Data._ID + "=" + dataId, null, callerIsSyncAdapter); 2493ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2494ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2495ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2496f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 24975aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 24982971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 24992971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 25002971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 25012971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 25022971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2503e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 25042971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 25052971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 25065aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 25072971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 25082971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 25092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 25102971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 251181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2512f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 251381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 25142971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2515508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2516508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2517eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 251843880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 25195aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteSettings(uri, selection, selectionArgs); 2520eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2521eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 252282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 2523eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 25241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 252681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 252781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 25283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 252981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2530508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 25314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 25324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 25332971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana private boolean readBooleanQueryParameter(Uri uri, String name, boolean defaultValue) { 25342971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final String flag = uri.getQueryParameter(name); 25352971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return flag == null 25362971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana ? defaultValue 25372971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana : (!"false".equals(flag.toLowerCase()) && !"0".equals(flag.toLowerCase())); 253894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 253994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 25405aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 254194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana final long groupMembershipMimetypeId = mOpenHelper 254294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2543de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 254494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 254594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 254694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 254794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2548f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2549de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 255094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 255194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 255294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2553f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2554de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 255594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 255694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 25571a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 255894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 255994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 256094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 25615aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2562e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 25631a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2564e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2565e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2566e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2567cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 2568cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2569cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null); 2570cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2571cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2572cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2573cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 2574cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2575cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2576cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2577cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2578cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2579cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2580cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2581cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2582f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana public int deleteRawContact(long rawContactId, boolean callerIsSyncAdapter) { 2583f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 258414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2585de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 258633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2587a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov mOpenHelper.removeContactIfSingleton(rawContactId); 2588cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 258933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 259033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 259133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 2592cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 259381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 259481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 2595cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 2596cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 2597cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2598cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2599cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2600cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2601cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 2602cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2603cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 26044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2605de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2606de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 2607bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2608b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2609b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2610b5a4add17815167d20a90645779df34cdf45280dFred Quintana 261135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 261200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 261300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 2614b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 2615b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 2616b5a4add17815167d20a90645779df34cdf45280dFred Quintana Object data = values.get(ContactsContract.SyncStateColumns.DATA); 2617b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 2618b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 2619b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2620b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2621f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2622f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 262300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 262435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2625b5a4add17815167d20a90645779df34cdf45280dFred Quintana return mOpenHelper.getSyncState().update(mDb, values, 2626b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 2627b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2628b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 2629b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 2630b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2631b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2632b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2633b5a4add17815167d20a90645779df34cdf45280dFred Quintana return mOpenHelper.getSyncState().update(mDb, values, 2634b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 2635b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 263635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2637d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 26388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 263900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 264000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 264100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2642d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 26438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 2644c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2645c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2646c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 26472e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 26482e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 26492e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 26502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 26512e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 26522e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 26532e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26542e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 26552e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 26568c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 26572e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 26582e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 26592e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 26607d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 26617d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 26627d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 26637d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 26647d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 26657d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 26667d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 26677d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 26687d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 26697d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 267020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2671944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2672f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 267381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2674f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 267581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 267620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 267720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2678c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 267948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 268048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 268148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 268248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2683f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 268481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2685f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 268681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 268700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 268800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 26897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 26915ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 26924529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 26937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 26947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26965ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 269733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 26984529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 26994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=" + rawContactId 27004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 27014529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 27024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContact(rawContactId, values); 27034529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 27047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 27057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 27067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2707ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 27085aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 2709f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 271081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2711f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 271281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2713ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2714ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2715ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2716ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2717ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 271873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String selectionWithId = (Groups._ID + "=" + groupId + " ") 271973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 27205aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 27215aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 272281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2723f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 272481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2725ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2726ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2727ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2728127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 2729de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 2730b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2731b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2732b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2733eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 27345aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateSettings(uri, values, selection, selectionArgs); 273543880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2736eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2737eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2738eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 273981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 274081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2741f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 274281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 274300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 274400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 274500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 27464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 27485aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 2749f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 275073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 275173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 2752f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 275373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 275473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 275573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 275673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 275773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 275873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 275973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 276073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2761ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 27621a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 27631a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 276494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 276594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 276694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 276794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 27685aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateSettings(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 2769e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 27701a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 27711a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2772e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2773e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2774e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2775e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 27764529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 27774529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 27784529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 27794529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 27804529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 278173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 27824529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 27834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov Cursor cursor = mDb.query(mOpenHelper.getRawContactView(), 278451bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 27854529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 27864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 27874529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 27884529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 27894529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 27904529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 27914529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 27924529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 27934529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 27944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 27954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 27964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 27974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 27984529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 27994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 280019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final String selection = RawContacts._ID + " = " + rawContactId; 280119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 280219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 280319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 280419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 280519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 280619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka null, null, null, null); 280719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 280819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 280919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 281019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 281119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 281219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 281319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 281419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 281519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 281619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 281719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int count = mDb.update(Tables.RAW_CONTACTS, values, selection, null); 28185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 2819433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 28204529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 2821433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 2822285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 2823285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateLookupKey(mDb, rawContactId); 2824285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 282519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 282619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 282719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka mInsertedRawContacts.add(rawContactId); 282819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 28295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 28305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 283133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 283233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 2833321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 2834f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 283520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 283620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 283720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 28385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 283920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 284020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 284120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 284220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 284320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 284420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 284520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 284620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 284770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 284870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 284920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 285020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 285120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 285270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 285320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 285470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 285520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 285670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 285720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 285870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 285920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 286020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2861653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 286220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2863653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2864653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 286514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 2866653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 2867653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 2868f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 286920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2870653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 2871653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 287220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 287320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2874653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 287520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 287620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2877f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 2878653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 2879653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 2880321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2881653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 288214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 2883a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2884f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana rowHandler.update(mDb, values, c, callerIsSyncAdapter); 28858e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 2886a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2887a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2888a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 28898e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2890653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 2891321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2892321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 28938c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 28948c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 28958c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 28968c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov Cursor cursor = mDb.query(mOpenHelper.getContactView(), 28978c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 28988c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 28998c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 29008c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 29018c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 29028c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 29038c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 29048c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 29058c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 29068c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 29078c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 29088c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 29098c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 29108c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 29118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 29128c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 2913d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 29148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 29158c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 2916d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 29178c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 2918d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 29198c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 2920d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 29218c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 2922d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 29238c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.STARRED, 2924d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 2925d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2926d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 29278c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 2928d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 2929d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2930d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 29318c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 2932c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 29338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2934c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 2935c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 29368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=" + contactId, null); 29378c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 29388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 29398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 29408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 29418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 29428c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 29438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 29448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 29458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 29468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 29478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 29488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 29498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.STARRED, 29508c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 29518c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 29528c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=" + contactId, null); 2953f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2954d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2955d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public void updateContactTime(long contactId, long lastTimeContacted) { 2956f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 2957d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(2, contactId); 2958f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.execute(); 2959d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2960d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2961127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 2962127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 29630c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 29640c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 296580c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 29660c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 29670c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 29680c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 29690c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 29700c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 29710c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 29720c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 2973b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2974127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 29750c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 29760c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 29770c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=" + rawContactId1 + " AND " 29780c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=" + rawContactId2, null); 29790c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 29806bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 29816bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 29820c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 29830c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 29840c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 29850c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 2986127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2987127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2988dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 2989dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 2990dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 29910c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long contactId1 = mOpenHelper.getContactId(rawContactId1); 29920c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 29930c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 29940c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long contactId2 = mOpenHelper.getContactId(rawContactId2); 29950c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 2996127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2997127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 2998127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 2999127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3000b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3001b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 300270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 300370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb = mOpenHelper.getWritableDatabase(); 300470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (mDb == null) return; 300570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 300670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong Set<Account> validAccounts = Sets.newHashSet(); 300770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accounts) { 300870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong validAccounts.add(new Account(account.name, account.type)); 300970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 301070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong ArrayList<Account> accountsToDelete = new ArrayList<Account>(); 301170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 301270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 301370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 301448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 30155f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana for (String table : new String[]{Tables.RAW_CONTACTS, Tables.GROUPS, Tables.SETTINGS}) { 30165f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // Find all the accounts the contacts DB knows about, mark the ones that aren't 30175f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // in the valid set for deletion. 30185f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Cursor c = mDb.rawQuery("SELECT DISTINCT account_name, account_type from " 30195f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + table, null); 30205f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana while (c.moveToNext()) { 30215f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (c.getString(0) != null && c.getString(1) != null) { 30225f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Account currAccount = new Account(c.getString(0), c.getString(1)); 30235f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (!validAccounts.contains(currAccount)) { 30245f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana accountsToDelete.add(currAccount); 30255f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana } 302670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 302770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 30285f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana c.close(); 302970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 303070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 303170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 30325f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 303370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong String[] params = new String[]{account.name, account.type}; 303470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.GROUPS 303570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 303670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.PRESENCE 303770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (SELECT " 303870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS 303970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?)", params); 304070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.RAW_CONTACTS 304170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 30425f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana mDb.execSQL("DELETE FROM " + Tables.SETTINGS 30435f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + " WHERE account_name = ? AND account_type = ?", params); 304470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 30454637c20c6b6d3b6f6671e6a44ed57f1e5b9c4484Dmitri Plotnikov mOpenHelper.getSyncState().onAccountsChanged(mDb, accounts); 304670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 304770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 304870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 304970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 305070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3051619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3052619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3053622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 3054622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 3055622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private static boolean areAllEmpty(ContentValues values, String[] keys) { 3056622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 3057622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (!TextUtils.isEmpty(values.getAsString(key))) { 3058622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return false; 3059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3060622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3061622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return true; 3062622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 3063622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 30644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 30654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 30664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 3067bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3068bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3069bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 30700b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 30714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 307235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3073d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 30741f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3075c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3076c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3077619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3078619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3079a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 30804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 308135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 308235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().query(db, projection, selection, selectionArgs, 308335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 308435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3085d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3086ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 3087619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3088619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3089619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3090d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 30914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3092ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 30934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + contactId); 30946bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 30956bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 30966bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 30975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 30985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 30995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 31005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 31015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 31025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 31035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 31055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 31065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 31075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 31085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov setTablesAndProjectionMapForContacts(lookupQb, projection); 31095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=" + contactId + " AND " + 31105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.LOOKUP_KEY + "="); 31115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhereEscapeString(lookupKey); 31125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, selectionArgs, sortOrder, 31135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 31145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 31155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 31165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 31185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 31195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 31215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 31225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 31235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 31245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3126ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3127ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 3128ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 31294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 31304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3131e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 31325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 31334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sb.toString()); 3134ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3135ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3136ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3137ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3138ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3139ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 31404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3141ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3142d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 31434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 31444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3145e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 31465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 31474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 31484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 31494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3150ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 3151ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 31524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 31534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 31544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3155d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3156d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final String starredQuery = qb.buildQuery(projection, Contacts.STARRED + "=1", 31574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3158d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3159d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3160d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3161ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 31624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 31634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3164d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3165d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String frequentQuery = qb.buildQuery(projection, 3166d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3167d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 31684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3169d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3170d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3171d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3172d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 31734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 31744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3175d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3176d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3177d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3178d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3179d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3180d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3181ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3182ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 3183b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 318471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 31854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3186b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3187b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3188b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3189b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3190d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 31914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 319282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 31934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 31946bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 31956bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 319600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3197ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 31983653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 319982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 32003653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 32013653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 32023653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 32033653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 32043653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 32054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 320682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 320789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 32082815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 32092815f58f72f109790585931f601a63ddc02536a5Evan Millar } 32102815f58f72f109790585931f601a63ddc02536a5Evan Millar 321148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 321282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 321348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 321448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 321548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 321648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 321748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3218ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 321982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 322089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3221ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 32224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 32234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 32245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 32255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 32265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 32275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 32285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 32295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 32305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null); 32315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 32325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 32335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 32345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 32355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 32365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 32375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 32385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 32395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 32405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 32415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 32425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 32435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 32445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 32455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 32465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 32475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 32484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + sb); 3249ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 32505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3251ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3252ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3253ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 32544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 325582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 325689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 32574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 32584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 32594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 326048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 326182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 326248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 326348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 326448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 326548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 326648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 32675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 326882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 326989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 32704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 32715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + Email.DATA + "="); 32724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhereEscapeString(uri.getLastPathSegment()); 32734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3274ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3275ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3276ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 32775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 327882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 327989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 32805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 32815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 32825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 32835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 32845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 32855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 32865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 32875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 32885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null); 32895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 32905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 32915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 32925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Email.DATA + " LIKE "); 32931e530df9f7e496dc47f77d4323c89bd413b79b64Dmitri Plotnikov sb.append(DatabaseUtils.sqlEscapeString(filterParam + '%')); 32945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 32955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + sb); 32965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 32975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 32985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 32995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 33005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3301ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 330282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 330389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 330489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3305ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3306ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3307ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 330848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 330982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 331048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 331148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 331248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 331348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 331448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 331548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 33165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 33174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getRawContactView()); 3318d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 331989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 33204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 33214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 33224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 33235ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 33245ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 33254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getRawContactView()); 3326d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 332789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 332889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 33294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 33304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 33314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 33325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 33335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 333482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 333589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=" + rawContactId); 3336e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3337e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3338e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 3339e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 334082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3341e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3342e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3343e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 33444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 334582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 334682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + ContentUris.parseId(uri)); 3347a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3348a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3349a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3350a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 33514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3352a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 3353a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 3354a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 3355e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 3356a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3357a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3358e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 3359e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov mOpenHelper.buildPhoneLookupAndContactQuery(qb, number); 3360e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 3361e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 3362e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 3363e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 3364e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 3365a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3366a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3367a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3368ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 336989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(mOpenHelper.getGroupView()); 3370ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 337189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3372ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3373ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3374ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3375ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3376ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 337789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(mOpenHelper.getGroupView()); 3378ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 337989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(Groups._ID + "=" + groupId); 3380ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3381ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3382ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3383ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 338489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(mOpenHelper.getGroupView() + " AS groups"); 3385ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 338689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 338789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 3388ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3389ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3390ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3391b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 33920c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 3393b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 3394b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3395b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3396b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 339731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 3398d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 33992d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 34002d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 34012d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 34022d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 340331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 3404d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 3405d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 340631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 340731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 340831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 340931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 34107581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 34117581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 34127581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 34132d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 341431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 341531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3416eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3417eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 3418eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 341989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3420e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3421e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 3422e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 3423e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final String groupMembershipMimetypeId = Long.toString(mOpenHelper 3424e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 342582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 342682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mOpenHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3427e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3428e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 342982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 343082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mOpenHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3431e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3432e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3433e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3434eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3435eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3436eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 343782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 3438a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov qb.setTables(Tables.PRESENCE + 3439a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 344082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON(" + StatusUpdates.DATA_ID + "=" + StatusUpdatesColumns.DATA_ID + ")"); 344182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 34425ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 34435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 34445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 344582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 3446373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setTables(Tables.PRESENCE); 344782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 344882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.appendWhere(StatusUpdates.DATA_ID + "=" + ContentUris.parseId(uri)); 34495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 34505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 34515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 3452c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 3453a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 3454c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3455c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3456c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 3457b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3458b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh(db, contactId, projection); 3459c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3460c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 34611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 34621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 34631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 34641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 34651b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 34661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 34671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 34681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 34691b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 34701b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 34711b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 34721b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 34731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 34741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 34751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 34761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 34771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 34781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 34791b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 34801b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 348171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 34821b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 34831b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 34841b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 34854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 3486f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 3487c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 34884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 34894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 34905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 34915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 34945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 34955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 3496038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 3497038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 3498038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 3499038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 35005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 35015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 35024f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 35034f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 35044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 35064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 35095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 35105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 35115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 35135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 35145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 35155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 35185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 35215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 35225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 35245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 35255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 35265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 35275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 35285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 35295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 35315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 35325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 35335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 35345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 35375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 35385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 35395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 35405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 35415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 35425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 35435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 35475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 35485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 35515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 35525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 35535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 35545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 35555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 35565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 35575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 35585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 35615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 35625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 35645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 35655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 35665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 35675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 35685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 35695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 35705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 35715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 35725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 35735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 35745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 35755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 35765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 35775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 35785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 35825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 35835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 35865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 35895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 35905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 35925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 35935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 35945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 35955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 35965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 35975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 35995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 36005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 36015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 36025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 36055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 36065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 36075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 36085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 36095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 36105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 36115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 36155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 36165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 36195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 36205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 36215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 36225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 36235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 36245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 36255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 36265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 36295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 36305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 36315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 36335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 36345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 36355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 36365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 36375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 36385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 36395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 36405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 36415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 36425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 36435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 36445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 36455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 36465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 36475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 36515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 36525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 36555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 36585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 36595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 36605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 36615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 36625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 36645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 36655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 36675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 36685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 36695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 36705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 36715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 36725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 36735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 36745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 36755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 36765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 36775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 36785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 36795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 36815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 36825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 36865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 36875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 36885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 36895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 36915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3692ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, String[] projection) { 369382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 369482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(mOpenHelper.getContactView()); 369582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (mOpenHelper.isInProjection(projection, 369682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 369782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 369882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 369982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 370082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (mOpenHelper.isInProjection(projection, 370182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 370282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 370382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 370482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 370582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 370682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 3707a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 3708a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ")"); 370982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 371082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 371182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 371282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 3713ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 371482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 371582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 371682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 371782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(mOpenHelper.getDataView()); 371882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 371982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 372082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (mOpenHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 372182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 372282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + AggregatedPresenceColumns.CONTACT_ID + "=" 372382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 372482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 372582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 372682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (mOpenHelper.isInProjection(projection, 372782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 372882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 372982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 373082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 373182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 373282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 373382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 373482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ")"); 3735ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 373682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 373782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 373882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 3739ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 3740ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 37414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 37424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 37434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 37444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 37454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 37464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 37474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 37484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 37494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 37504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 37514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 37524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 37534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3754e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 3755e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 3756e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 3757e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(accountName)) { 3758e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 3759e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 3760e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 3761e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 3762e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 3763e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 3764e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 3765e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 3766e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3767e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 3768e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 3769e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 3770e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3771e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3772e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 37737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 3774c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 3775c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 3776c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 3777c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 3778c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 3779c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private String getLimit(Uri url) { 3780c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limitParam = url.getQueryParameter("limit"); 3781c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 3782c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3783c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3784c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 3785c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 3786c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 3787c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 3788c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 3789c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3790c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3791c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 3792c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 3793c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 3794c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3795c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3796c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3797c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 37985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 37995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 38005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 38015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 38025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 38035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 38045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 38055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 38065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 38075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 38085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 38095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 38105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 38125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 38135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 38145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 38165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 38175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 38195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 38205e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38215e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 38225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 38235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 38255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 38265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 38275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 382800ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 38294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (mOpenHelper.hasRestrictedAccess()) { 383070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 383170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 38326cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 383370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 383470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 383570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 383670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 38374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (mOpenHelper.hasRestrictedAccess()) { 383870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 383967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 38405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 38415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 3842619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3843619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3844619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3845b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 3846b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 3847b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 3848b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 3849d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 3850b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 3851b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 3852b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3853b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3854b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 3855b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3856b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 3857b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mOpenHelper.getDataView() + 3858b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 3859b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=" + contactId; 3860b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 3861b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, null); 3862d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3863d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3864d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_LOOKUP: 3865d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_LOOKUP_ID: { 3866d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // TODO: optimize lookup when direct id provided 3867d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 3868d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 3869d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String selection = RawContacts.CONTACT_ID + "=" + contactId; 3870d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3871d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 3872d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 3873d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 3874d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 3875d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey outputRawContactsAsVCard(localStream, selection, null); 3876d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 3877d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3878b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3879b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 3880b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("No file at: " + uri); 3881b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3882b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3883b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3884d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 3885d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String VCARD_TYPE_DEFAULT = "default"; 3886d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3887d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 3888d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 3889d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 3890d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 3891d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 3892d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 3893d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 3894d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 3895d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3896d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 3897d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 3898d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3899d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 3900d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 3901d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 3902b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3903d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 3904d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 3905d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 3906d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3907d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 3908d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3909d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3910d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 3911d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 3912d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 3913d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 3914d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 3915d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 3916d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 3917d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 3918d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final VCardComposer composer = new VCardComposer(context, VCARD_TYPE_DEFAULT, false); 3919d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 3920d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3921d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // TODO: enforce the callers security clause is used 3922d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.init(selection, selectionArgs)) 3923d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 3924d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3925d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 3926d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 3927d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 3928d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3929d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3930d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 3931d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3932b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3933bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3934bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov private static Account readAccountFromQueryParams(Uri uri) { 3935bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String name = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 3936bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov final String type = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 3937bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 3938bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return null; 3939bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 3940bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov return new Account(name, type); 3941bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov } 3942bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3943bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3944619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 39457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 39467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 39477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 3948d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static class RawContactsEntityIterator implements EntityIterator { 39497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 39507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 39517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 39537a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 39547a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 39557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 39567a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 39577a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 39587a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 39597a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 39607a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 39617a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 39627a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 39637a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 39647a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 39657a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 39667a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 39677a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 39687a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 39697a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 39707a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 39717a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4}; 39727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] PROJECTION = new String[]{ 39746cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 39756cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 39766cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.SOURCE_ID, 39776cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.VERSION, 39786cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.DIRTY, 39797a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data._ID, 39807a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RES_PACKAGE, 39817a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.MIMETYPE, 39827a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 39837a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 39847a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 39857a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 39867a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 39877a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 39887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 39897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 39907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 39917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 39927a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 39937a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 39947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 39957a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 39967a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 39977a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 39987a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 39997a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 40007a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4, 40017a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RAW_CONTACT_ID, 40027a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.IS_PRIMARY, 40033cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar Data.IS_SUPER_PRIMARY, 40047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA_VERSION, 40057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana GroupMembership.GROUP_SOURCE_ID, 40067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC1, 40077a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC2, 40087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC3, 400994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana RawContacts.SYNC4, 401038446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey RawContacts.DELETED, 4011c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.CONTACT_ID, 4012c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.STARRED}; 4013035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 4014035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 4015035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 4016035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 4017035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 4018035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 4019035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 402067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_RES_PACKAGE = 6; 402167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_MIMETYPE = 7; 402267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA1 = 8; 40237a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_RAW_CONTACT_ID = 27; 40247a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_IS_PRIMARY = 28; 40253cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_IS_SUPER_PRIMARY = 29; 40263cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DATA_VERSION = 30; 40273cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_GROUP_SOURCE_ID = 31; 40283cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC1 = 32; 40293cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC2 = 33; 40303cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC3 = 34; 40313cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC4 = 35; 40323cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DELETED = 36; 40333cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_CONTACT_ID = 37; 40343cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_STARRED = 38; 40357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4036d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey public RawContactsEntityIterator(ContactsProvider2 provider, String contactsIdString, Uri uri, 40377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 40387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 40397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final String updatedSortOrder = (sortOrder == null) 40417a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana ? Data.RAW_CONTACT_ID 40427a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana : (Data.RAW_CONTACT_ID + "," + sortOrder); 40437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 40457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 4046226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setTables(Tables.CONTACT_ENTITIES); 40477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 40485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.appendWhere(Data.RAW_CONTACT_ID + "=" + contactsIdString); 40497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40506cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 40516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 4052035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName)) { 405323c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana if (contactsIdString != null) { 405423c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana qb.appendWhere(" AND "); 405523c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana } 40566cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 4057035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 40586cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 4059035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 4060035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 40617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 40627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana null, null, updatedSortOrder); 40637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 40647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4066038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4067038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4068038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4069038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4070038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4071038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4072038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana 40737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 40747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 40757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 40767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 40787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 40797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40807e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 40827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 40837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 40847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 40877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 40907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 40917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 40927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 40947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 40957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 40987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40997a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final long rawContactId = c.getLong(COLUMN_RAW_CONTACT_ID); 41007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 41017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 41027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 41036cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 41046cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 41055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 41066cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 41076cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 41086cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 41097a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC1, c.getString(COLUMN_SYNC1)); 41107a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC2, c.getString(COLUMN_SYNC2)); 41117a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC3, c.getString(COLUMN_SYNC3)); 41127a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC4, c.getString(COLUMN_SYNC4)); 411394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana contactValues.put(RawContacts.DELETED, c.getLong(COLUMN_DELETED)); 411438446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey contactValues.put(RawContacts.CONTACT_ID, c.getLong(COLUMN_CONTACT_ID)); 4115c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey contactValues.put(RawContacts.STARRED, c.getLong(COLUMN_STARRED)); 41167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 41177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 41187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 41197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 41207a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana if (rawContactId != c.getLong(COLUMN_RAW_CONTACT_ID)) { 41217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 41227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 412323c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// if (c.isNull(COLUMN_CONTACT_ID)) { 412423c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// continue; 412523c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana// } 41267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 41277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 412823c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data._ID, c.getLong(COLUMN_DATA_ID)); 41297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 41307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 413123c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_PRIMARY, c.getLong(COLUMN_IS_PRIMARY)); 413223c48e7953e2f854eeef6d8e3d3c1b901fc571edFred Quintana dataValues.put(Data.IS_SUPER_PRIMARY, c.getLong(COLUMN_IS_SUPER_PRIMARY)); 41337a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 41349261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 41359261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana dataValues.put(GroupMembership.GROUP_SOURCE_ID, 41369261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.getString(COLUMN_GROUP_SOURCE_ID)); 41379261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 41387a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 41397a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana for (int i = 0; i < DATA_KEYS.length; i++) { 41407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 41417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 41427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 41437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 41447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 41457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 41467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 41477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 41487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 41497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 41507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 41517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 41527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 41557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 41567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 41577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 41587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4161226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana /** 4162226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 4163226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 4164226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana */ 4165226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static class GroupsEntityIterator implements EntityIterator { 4166226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private final Cursor mEntityCursor; 4167226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private volatile boolean mIsClosed; 4168226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4169226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final String[] PROJECTION = new String[]{ 4170226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups._ID, 4171226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_NAME, 4172226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_TYPE, 4173226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.SOURCE_ID, 4174226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.DIRTY, 4175226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.VERSION, 4176226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.RES_PACKAGE, 4177226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE, 4178226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE_RES, 41797a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.GROUP_VISIBLE, 41807a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC1, 41817a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC2, 41827a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC3, 41837a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC4, 41847a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYSTEM_ID, 418594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.NOTES, 41861a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey Groups.DELETED, 41871a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey Groups.SHOULD_SYNC}; 4188226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4189226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ID = 0; 4190226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_NAME = 1; 4191226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_TYPE = 2; 4192226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_SOURCE_ID = 3; 4193226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_DIRTY = 4; 4194226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_VERSION = 5; 4195226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_RES_PACKAGE = 6; 4196226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE = 7; 4197226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE_RES = 8; 4198226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_GROUP_VISIBLE = 9; 41997a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 10; 42007a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 11; 42017a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 12; 42027a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 13; 42037a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYSTEM_ID = 14; 42047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_NOTES = 15; 420594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana private static final int COLUMN_DELETED = 16; 42061a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private static final int COLUMN_SHOULD_SYNC = 17; 4207226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4208226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 4209226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 4210226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = false; 4211226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4212226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String updatedSortOrder = (sortOrder == null) 4213226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ? Groups._ID 4214226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana : (Groups._ID + "," + sortOrder); 4215226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4216226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 4217226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 421889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(provider.mOpenHelper.getGroupView()); 4219226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setProjectionMap(sGroupsProjectionMap); 4220226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (groupIdString != null) { 4221226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups._ID + "=" + groupIdString); 4222226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4223226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountName = uri.getQueryParameter(Groups.ACCOUNT_NAME); 4224226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountType = uri.getQueryParameter(Groups.ACCOUNT_TYPE); 4225226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!TextUtils.isEmpty(accountName)) { 4226226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups.ACCOUNT_NAME + "=" 4227226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4228226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + Groups.ACCOUNT_TYPE + "=" 4229226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 4230226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4231226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 4232226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana null, null, updatedSortOrder); 4233226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToFirst(); 4234226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4235226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4236226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public void close() { 4237226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4238226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("closing when already closed"); 4239226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4240226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = true; 4241226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.close(); 4242226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4243226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4244226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public boolean hasNext() throws RemoteException { 4245226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4246226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 4247226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4248226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4249226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return !mEntityCursor.isAfterLast(); 4250226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4251226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4252038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4253038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4254038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4255038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4256038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4257038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4258e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4259226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public Entity next() throws RemoteException { 4260226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4261226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 4262226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4263226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!hasNext()) { 4264226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 4265226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4266226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4267226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 4268226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4269226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final long groupId = c.getLong(COLUMN_ID); 4270226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4271226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana // we expect the cursor is already at the row we need to read from 4272226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ContentValues groupValues = new ContentValues(); 4273226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 4274226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 4275226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups._ID, groupId); 4276226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 4277226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 4278226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 4279226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 4280226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 4281226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 4282226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 42837a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC1, c.getString(COLUMN_SYNC1)); 42847a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC2, c.getString(COLUMN_SYNC2)); 42857a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC3, c.getString(COLUMN_SYNC3)); 42867a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC4, c.getString(COLUMN_SYNC4)); 42877a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYSTEM_ID, c.getString(COLUMN_SYSTEM_ID)); 428894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana groupValues.put(Groups.DELETED, c.getLong(COLUMN_DELETED)); 42897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.NOTES, c.getString(COLUMN_NOTES)); 42901a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey groupValues.put(Groups.SHOULD_SYNC, c.getString(COLUMN_SHOULD_SYNC)); 4291226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Entity group = new Entity(groupValues); 4292226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4293226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToNext(); 4294226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4295226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return group; 4296226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4297226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4298226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4299a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 43007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 43017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 4302568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 4303568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 43047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 43057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 43065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: 43075ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: 43087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 43095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (match == RAW_CONTACTS_ID) { 43107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 43117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 43127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4313d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return new RawContactsEntityIterator(this, contactsIdString, 43147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana uri, selection, selectionArgs, sortOrder); 4315226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS: 4316226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS_ID: 4317226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String idString = null; 4318226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (match == GROUPS_ID) { 4319226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana idString = uri.getPathSegments().get(1); 4320226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4321226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4322226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return new GroupsEntityIterator(this, idString, 4323226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana uri, selection, selectionArgs, sortOrder); 43247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 43257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 43267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 43277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 43287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 43294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 43304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4331a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 43324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4333b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4334b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP: 4335be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 4336b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4337b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4338b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4339b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4340be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4341b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4342b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4343508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4344b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return mOpenHelper.getDataMimeType(ContentUris.parseId(uri)); 434548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 434648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 434748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 434848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 434948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 435048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 435148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 435248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 435348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 435448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 435548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 435648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4357b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4358b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4359b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4360b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4361b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4362b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4363b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4364b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4365c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4366c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4367c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4368c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 436961efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 437061efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 43714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 43724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 43737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 437425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private void setDisplayName(long rawContactId, String displayName, int bestDisplayNameSource) { 43753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 437625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindString(1, displayName); 43773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 437825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindNull(1); 43793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 438025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(2, bestDisplayNameSource); 438125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(3, rawContactId); 438225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 43833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 43843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 438573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 438673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 438773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 438873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 438973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.bindLong(1, rawContactId); 439073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.execute(); 439173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 439273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4393c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4394c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 4395c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 4396c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4397c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4398c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4399653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 4400c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 4401653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 4402653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 4403c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 4404c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4405c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 4406c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4407c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 4408c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 4409c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4410c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4411c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4412653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 4413c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 4414653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 4415653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 4416c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 4417c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4418ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4419f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 4420f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 4421f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4422f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4423f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4424f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); 4425f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (tokens.length == 0) { 4426f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4427f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4428f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4429f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String address = tokens[0].getAddress(); 4430f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int at = address.indexOf('@'); 4431f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (at != -1) { 4432f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov address = address.substring(0, at); 4433f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4434f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4435f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4436f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 4437f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4438f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4439f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4440f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 4441f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4442f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 4443f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 4444f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4445f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4446f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4447f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4448f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 4449f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4450f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4451a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 4452a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 4453a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 4454a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4455a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 4456a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4457a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 4458a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 4459a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 4460a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4461a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 4462f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4463f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name) { 4464f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name); 4465f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4466f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4467f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4468f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Returns nickname cluster IDs or null. Maintains cache. 4469f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4470f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4471f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SoftReference<String[]> ref; 4472f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4473f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4474f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (mNicknameClusterCache.containsKey(normalizedName)) { 4475f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = mNicknameClusterCache.get(normalizedName); 4476f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (ref == null) { 4477f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return null; 4478f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4479f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = ref.get(); 4480f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4481f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4482f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4483f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (clusters == null) { 4484f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = loadNicknameClusters(normalizedName); 4485f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = clusters == null ? null : new SoftReference<String[]>(clusters); 4486f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4487f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNicknameClusterCache.put(normalizedName, ref); 4488f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4489f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4490f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4491f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4492f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4493f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] loadNicknameClusters(String normalizedName) { 4494f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 4495f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4496f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupQuery.TABLE, NicknameLookupQuery.COLUMNS, 4497f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.NAME + "=?", new String[] { normalizedName }, 4498f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov null, null, null); 4499f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov try { 4500f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int count = cursor.getCount(); 4501f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (count > 0) { 4502f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = new String[count]; 4503f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov for (int i = 0; i < count; i++) { 4504f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.moveToNext(); 4505f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters[i] = cursor.getString(NicknameLookupQuery.CLUSTER); 4506f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4507f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4508f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } finally { 4509f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.close(); 4510f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4511f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4512f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4513f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4514f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 4515f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4516f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 4517f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 4518f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4519f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4520f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4521f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 4522f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 4523f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 4524f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4525f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4526f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4527f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4528f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return ContactsProvider2.this.getCommonNicknameClusters(normalizedName); 4529f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4530f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4531f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4532f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4533f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 4534f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4535f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 4536f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 1, rawContactId); 4537f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 2, dataId); 4538f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 3, lookupType); 4539f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 4, name); 4540f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 4541f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4542f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4543f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4544f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 4545f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4546f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 4547f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupDelete, 1, dataId); 4548f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 4549f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4550f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 45512d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 4552d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4553d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 4554d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4555d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 4556d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 4557d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 4558d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 4559e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 4560d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN(" 4561d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 4562d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 4563d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.NICKNAME + "," 4564d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.ORGANIZATION + "))"); 4565e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 4566e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 45675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 4568c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4569c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 4570c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 4571c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4572c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4573a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 4574c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit) { 45755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), limit); 45765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 45785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 45795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String limit) { 4580d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4581d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + NameLookupColumns.RAW_CONTACT_ID + 4582d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 4583d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 4584d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 45855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 4586a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 4587a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 4588a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 4589d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 4590a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.ORGANIZATION + ")"); 45913de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 4592c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limit != null) { 4593c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(" LIMIT ").append(limit); 4594c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4595c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(")"); 4596ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4597ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 45984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 45994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 46004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 46014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 4602b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 4603b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 4604b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 4605b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 4606b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 46074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 46084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 4609b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 4610b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4611b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4612caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 4613caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 4614caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 4615caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 4616df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 4617df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 4618caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 4619caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 4620caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 4621caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 46226f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 4623caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 46246f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 4625caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 46264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 4627