ContactsProvider2.java revision 2d89933b87a15ae5ed5d6b6ec4220ac085695ada
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; 373de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.OpenHelper.Tables; 383de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.google.android.collect.Lists; 393de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.google.android.collect.Maps; 403de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.google.android.collect.Sets; 413de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 42b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 43caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 4470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wongimport android.accounts.OnAccountsUpdatedListener; 45c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 46568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 47568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 4835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 4967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 5135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.Entity; 5267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.EntityIterator; 53568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 543d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 5567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 563de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.content.SharedPreferences.Editor; 57b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 59ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 60b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 61b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 64c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 66d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 67b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 680e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 69d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 71508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 723de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 733de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.LiveFolders; 743de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.OpenableColumns; 753de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.SyncStateContract; 76b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 773de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 783de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 793de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 803de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 813de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Presence; 823de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 833de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 85ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 86ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 90de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 91b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 924097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 9367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 94a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 95a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 96f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Token; 97f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer; 98c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 100d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 101b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 102d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 103d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 104f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikovimport java.lang.ref.SoftReference; 1057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 107b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1080e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 110622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 111b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1120e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 113ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 11970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wongpublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdatedListener { 120caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 121bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 122bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 123bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 125619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 126619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 127619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1313d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1323d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1333d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1343d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1353d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1390e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1400e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 141a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 143d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 144d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.TIMES_CONTACTED + " DESC, " 1459b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 146d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 147d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 148d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 149d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 150d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 151d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 1604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 1644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1656bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1666bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 167ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 16848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 16948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 17048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 17148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 17248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 17348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 17448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 17548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 176a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1776bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1786bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 179b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 180b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 181b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 1821f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE = 7000; 1831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE_ID = 7001; 1841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 18531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 18631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 187eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 188eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 189ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 190ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 191ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 192ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 19335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 194b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 19535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 196c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 197c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 198c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 199a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov private static final int DATA_WITH_PRESENCE = 13000; 20019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri 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, 2433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov StructuredName.DISPLAY_NAME, 2443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 0; 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 1; 248f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 2; 2493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DISPLAY_NAME = 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 29725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private static final HashMap<String, Integer> sDisplayNameSources; 2983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov static { 29925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources = new HashMap<String, Integer>(); 30025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(StructuredName.CONTENT_ITEM_TYPE, 30125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.STRUCTURED_NAME); 30225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Organization.CONTENT_ITEM_TYPE, 30325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.ORGANIZATION); 30425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Phone.CONTENT_ITEM_TYPE, 30525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.PHONE); 30625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov sDisplayNameSources.put(Email.CONTENT_ITEM_TYPE, 30725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov DisplayNameSources.EMAIL); 3083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 30931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 310caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov public static final String DEFAULT_ACCOUNT_TYPE = "com.google.GAIA"; 311df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 312caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 313038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 314038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 315e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 317ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains contacts and presence columns */ 318ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov private static final HashMap<String, String> sContactsWithPresenceProjectionMap; 319ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 320d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 3214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3259261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 326e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 327ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 328ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 329ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 330ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 331373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 332b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 333eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 334eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 335373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains Presence columns */ 336373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov private static final HashMap<String, String> sPresenceProjectionMap; 33719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov /** Contains Presence columns */ 338a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov private static final HashMap<String, String> sDataWithPresenceProjectionMap; 3391b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3401b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 342b67163a1088f09c59f324350662eb18772fac6b6Evan Millar /** Sql where statement for filtering on groups. */ 343d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String sContactsInGroupSelect; 34419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 345c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 346c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 348c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 349d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Precompiled sql statement for incrementing times contacted for an contact */ 350f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private SQLiteStatement mLastTimeContactedUpdate; 3513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 35225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 35373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** Precompiled sql statement for marking a raw contact as dirty */ 35473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private SQLiteStatement mRawContactDirtyUpdate; 355e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov /** Precompiled sql statement for setting an aggregated presence */ 356e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov private SQLiteStatement mAggregatedPresenceReplace; 357e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov /** Precompiled sql statement for updating an aggregated presence status */ 358e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov private SQLiteStatement mAggregatedPresenceStatusUpdate; 359f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 360f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 361a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 3624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 3634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 364a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 365d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 366d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 367d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 3683653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 3693653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 3702d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 3712d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 3723653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 3735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 3745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 3755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 3765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 377ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 378ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 3795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 3803653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 3815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 3825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 3835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 384b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 3864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 387ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 38848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 3895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 390ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 3914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 39248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 3935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 3945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 3954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 396ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 39748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 3981f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 399ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 400ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 401ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 402ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 40335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 404b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 405b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 40635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 407a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 408b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 409b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 410b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 411b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 413eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 414eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 415bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence", PRESENCE); 416bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence/#", PRESENCE_ID); 4171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 418c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 419c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 420c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 421c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 422c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 423c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 424c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 4291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 4301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 4311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 4321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 4331b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 43419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov // Private API 435a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data_with_presence", DATA_WITH_PRESENCE); 43619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 43719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 43819a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 439038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 440038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 441e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 4434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 4444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 4454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 4464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 4474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 4484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 4494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 4504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 451f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 4524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 4535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 454d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey sContactsProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 455d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 456d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey sContactsProjectionMap.put(OpenableColumns.SIZE, "0 AS " + OpenableColumns.SIZE); 4574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 458ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap = new HashMap<String, String>(); 459ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap.putAll(sContactsProjectionMap); 460ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap.put(Contacts.PRESENCE_STATUS, 461e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov Presence.PRESENCE_STATUS + " AS " + Contacts.PRESENCE_STATUS); 462ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov sContactsWithPresenceProjectionMap.put(Contacts.PRESENCE_CUSTOM_STATUS, 463ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Presence.PRESENCE_CUSTOM_STATUS + " AS " + Contacts.PRESENCE_CUSTOM_STATUS); 4644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 4664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 4674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 4684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 4694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 4704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 4714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 4724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 4734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 4744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 4754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 4764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 4774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 4784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 4794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 4804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 4814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 4824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 4834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 4844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 4852815f58f72f109790585931f601a63ddc02536a5Evan Millar 4864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 4874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 4884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 4894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 4904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 4914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 4924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 4934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 4944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 4954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 4964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 4974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 4984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 4994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 5004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 5014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 5024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 5034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 5044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 5054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 5064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 5074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 5084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 5094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 5134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 51956d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 5274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 528a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 5305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 5315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 5325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 5335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 5345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 5355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 5365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 5375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 5385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 5395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 5405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 5415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 5425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 5435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 5445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 5455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 5465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 5475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 5485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 5495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 5505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 5515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 5525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 5535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 5545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 5555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 5565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 5575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5588f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 5595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 5605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 5615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 5665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 5675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 5685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 569e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 570e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 571e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_ID + " AS " + PhoneLookup._ID); 57256d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 57356d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar Contacts.LOOKUP_KEY + " AS " + PhoneLookup.LOOKUP_KEY); 574e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 575e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + PhoneLookup.DISPLAY_NAME); 576e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 577e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 578e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 579e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 580e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " + PhoneLookup.TIMES_CONTACTED); 581e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 582e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_STARRED + " AS " + PhoneLookup.STARRED); 583e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 584e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 585e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 586e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.PHOTO_ID + " AS " + PhoneLookup.PHOTO_ID); 587e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 588e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " + PhoneLookup.CUSTOM_RINGTONE); 589e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 590e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Contacts.HAS_PHONE_NUMBER + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 591e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 592e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 593e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 594e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 595e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 596e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 597e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 598e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 599e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 6009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 601e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov HashMap<String, String> columns; 6027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 603ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 604ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 60589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 606035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 607035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 6089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 6099261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 6109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 61189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 612ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 61367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 614ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 6153cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 61694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 6173cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 61838446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 61989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 62089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 62189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 62289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 623ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 624ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 6256cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 626ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 627ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 628d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 629d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 630ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 631ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 632ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 633d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 634d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 635ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 636f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 637ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 638ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 639b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 640b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 641b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 642b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 6430c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 6440c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 645b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 646b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 647eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 648eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 649eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 650eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 651eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 652eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 653341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 654341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 655341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 656fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 657341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 658341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 659341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 66068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 66168936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 66268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 66368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 66468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 665e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 66668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 66768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 66868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 669eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 670eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 671373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 672373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence._ID, Presence._ID); 6734dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 674373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.DATA_ID, Presence.DATA_ID); 675373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_ACCOUNT, Presence.IM_ACCOUNT); 676373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_HANDLE, Presence.IM_HANDLE); 6774dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(Presence.PROTOCOL, Presence.PROTOCOL); 6784dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(Presence.CUSTOM_PROTOCOL, Presence.CUSTOM_PROTOCOL); 679373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.PRESENCE_STATUS, Presence.PRESENCE_STATUS); 680373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.PRESENCE_CUSTOM_STATUS, Presence.PRESENCE_CUSTOM_STATUS); 681373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov sPresenceProjectionMap = columns; 682373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov 683a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap = new HashMap<String, String>(); 684a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap.putAll(sDataProjectionMap); 685a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap.put(Presence.PRESENCE_STATUS, 686e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov Presence.PRESENCE_STATUS); 687a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov sDataWithPresenceProjectionMap.put(Presence.PRESENCE_CUSTOM_STATUS, 688e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov Presence.PRESENCE_CUSTOM_STATUS); 68919a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 6901b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 6911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 6921b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 6931b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 6941b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 6951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 6961b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 6971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 6981b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 6991b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 7001b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 7011b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 7024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsInGroupSelect = Contacts._ID + " IN " 7034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 7044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 7054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 7064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 7074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 7084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 7094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 7104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 7114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " FROM " + Tables.GROUPS 7124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 7134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 7144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 7153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 7163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 7173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 7183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 7193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 721653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 7223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 7243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 7253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 727653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 728653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 729653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mMimetypeId = mOpenHelper.getMimeTypeId(mMimetype); 730653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 731653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 732653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 733653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 7343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 7353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 7363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 7375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 738e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 739e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 740e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 741e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 742653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 743e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 744e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 745e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 7463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 7493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 7503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 7513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 752653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 753f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 75414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 75514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 756653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 757653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 758653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 759653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 760653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 761653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 762653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 763653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 764653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 765653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 766653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 767653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 768653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 769653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 770653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 771653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 772653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 773653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " = " + dataId, null); 774653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 775653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 776f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 777653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 778653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 7793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 78214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 78314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 78414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 7853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 7863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 7875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 7883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 7903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 7935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long newPrimaryId = findNewPrimaryDataId(db, rawContactId); 7943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (newPrimaryId != -1) { 79514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov setIsPrimary(rawContactId, newPrimaryId, getMimeTypeId()); 7963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected long findNewPrimaryDataId(SQLiteDatabase db, long rawContactId) { 800e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 801e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 8025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Cursor c = queryData(db, rawContactId); 8033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 804e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 80514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 806f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 807e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 808e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 809e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 810e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 8113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 8133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 8143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 815e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return primaryId; 816e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 817e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 818e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 819e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 820e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 821e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 822e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 823e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 8243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected Cursor queryData(SQLiteDatabase db, long rawContactId) { 82714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return db.query(DataDeleteQuery.TABLE, DataDeleteQuery.CONCRETE_COLUMNS, 82814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId + 82914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov " AND " + MimetypesColumns.MIMETYPE + "='" + mMimetype + "'", 8303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov null, null, null, null); 8313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 83325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 8343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String bestDisplayName = null; 83525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 83625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov 83767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Cursor c = db.query(DisplayNameQuery.TABLE, DisplayNameQuery.COLUMNS, 8385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId, null, null, null, null); 8393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 8403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov while (c.moveToNext()) { 8413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String mimeType = c.getString(DisplayNameQuery.MIMETYPE); 8423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov boolean primary; 8433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String name; 8443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) { 8463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov name = c.getString(DisplayNameQuery.DISPLAY_NAME); 8473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov primary = true; 8483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 849f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov name = c.getString(DisplayNameQuery.DATA1); 8503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov primary = (c.getInt(DisplayNameQuery.IS_PRIMARY) != 0); 8513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 85301911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (name != null) { 85425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov Integer source = sDisplayNameSources.get(mimeType); 85501911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov if (source != null 85601911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov && (source > bestDisplayNameSource 85701911fa9cfa21f198fd767eedde072acbb879f28Dmitri Plotnikov || (source == bestDisplayNameSource && primary))) { 85825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov bestDisplayNameSource = source; 8593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov bestDisplayName = name; 8603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 8653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 8663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 86825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov setDisplayName(rawContactId, bestDisplayName, bestDisplayNameSource); 869285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 870285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateDisplayName(db, rawContactId); 871285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 8723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 873a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 874a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 875a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return true; 876a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 877622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 878622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 879622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 880622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * as baseline, but augmented with any updates. 881622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 882622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 883622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 884622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 885622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=" + dataId, 886622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey null, null, null, null); 887622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 888622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 889622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 890622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 891622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.put(key, cursor.getString(i)); 892622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 893622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 894622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 895622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 896622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 897622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 898622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 899622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 9003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 9033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 9053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 9063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 910622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 9113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 912622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 9133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 914622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 9153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 9185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 919622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 92014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 92114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 92214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 923f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 924f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 92525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 92614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 92714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 92814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 92914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 93014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 931f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 932622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 933622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 934cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 935622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 936622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 93714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 938f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 93914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 940f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 941f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 942f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 943f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 94414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 94525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 94614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 94714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 94814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 94914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 95014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 95114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 95214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 95314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 95414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 955f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 95625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 95714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 9583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 961622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 9623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 963622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 964622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 965622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 966622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 9673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 968622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 969622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 970622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 971622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 972622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 973622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 974622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 975622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 976622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 977622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 978622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 979622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 980622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 9818c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 982622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 983622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 984622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } else if (!touchedUnstruct && touchedStruct) { 9858c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 986622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 987622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(name); 988622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 989622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 990622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 991622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 992622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 993622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 994622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 995622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 996622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 997622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 998622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 999622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1000622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1001622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1002622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1003622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1004622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1005622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1006622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1007622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1008622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1009f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1010622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1011622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1012622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1013f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1014622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1015622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1016622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1017622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1018622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1019622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1020622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1021622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1022622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1023622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1024622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1025622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1026622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1027622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1028622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1029622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1030622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1031622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 1032622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 1033622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1034622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 1035622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1036622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1037622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1038622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1039622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1040622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1041622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 1042622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } else if (!touchedUnstruct && touchedStruct) { 1043622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1044622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1045622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 10463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 10513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 10533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 10543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 10563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 10583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 10593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 10625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1063622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1064622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1065622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1067622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1068622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1069f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1070622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1071622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1072622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1073f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1074622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1076622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1077622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1078622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1079622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1080622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1081622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1082622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1083622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 10843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1085622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1086622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1087622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1088622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1089622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 10943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 10963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 10973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 11015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long id = super.insert(db, rawContactId, values); 110225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 11033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return id; 11043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 110714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1108f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 110914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 111014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1111f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 111214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 111325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 111414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 111514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 111614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 111714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 111814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 111914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 112014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 112125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 112214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 112314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 112414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 112514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 11263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 11273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 11283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 11293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 11303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 11313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 11323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1134a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1135a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1136a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1137a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1138a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 11393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1141e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1142e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1143e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1144e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1145e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1146e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1147e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 11485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 114914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 115014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 115114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 115214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 115325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1154f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 115514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 115614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 115714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 115814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 115914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1160f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 116114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 116214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 116314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String address = values.getAsString(Email.DATA); 116414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1165f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 116614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1167f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1168f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 116925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 117014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 117114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 117214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 117314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 117414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 117514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 117614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 117714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 117814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1179f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 118025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 118114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1182e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1183e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1184e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1185e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1186e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1187e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1188e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1189e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1190e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1191e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1192e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1193e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1194e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1195e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 119614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 119714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 119814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 119914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 120014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 120114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 120214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 120314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 120414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 120514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 120614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 120714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 120825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1209f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 121014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 121114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 121214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 121314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 121414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1215f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 121614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 121714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 121814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 121914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1220f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 122114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1222f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1223f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 122425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 122514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 122614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 122714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 122814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 122914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 123014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 123114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 123214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 123314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1234f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 123525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 123614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 123714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 123814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 123914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 12403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 12413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 12433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 12443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 12475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 12480b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 12490b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 12500b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 12510b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1252653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 12530b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1254653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 12550b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1256285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 125725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 12580b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 12590b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 12600b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1261653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1262653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1263653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1264653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1265653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1266f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 126714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 126814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 12690b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 12700b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 12710b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1272653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1273f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1274653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 12750b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1276285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 127725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 12780b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 1279f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 12800b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 128114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 128214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 128314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 128414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 128514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 128614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 128714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 128814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 128914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 129014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1291285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 129225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 129314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1294653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1295653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1296653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1297e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1298e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1299e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1300e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1301653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1302653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1303653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1304e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1305653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1306653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1307e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1308653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 13095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1310653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1311e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 1312653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1313653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1314653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=" + dataId, null); 1315e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 13163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 13203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 13213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 13223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 13233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 13243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 13253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 13263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 13273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 13283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 13293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 13303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1334653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1335653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1336653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1337653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1338653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1339653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1340653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1341653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1342653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 13430be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 13440be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 13450be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1346653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1347653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1348653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1349653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1350f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 135114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1352653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1353f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 13540be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 13550be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 13560be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 13570be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 13580be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 13590be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 13600be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 13610be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 13620be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 13630be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 13640be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 13650be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 13660be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 13670be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 13680be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov mOpenHelper.updateContactVisible(contactId); 13690be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1370653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1371653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1372653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1373653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1374653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1375653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1376653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1377653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1378653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1379653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1380653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1381653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1382653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1383653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1384653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1385653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1386653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1387653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1388653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1389653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1390653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1391653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1392653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1393653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1394653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId); 1395653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1396653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1397653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1398653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1399a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1400a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1401a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1402a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1403a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1404653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1405653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1406a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1407a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1408a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1409a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1410a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1411a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1412a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1413a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1414a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1415285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1416285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1417285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1418a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1419a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1420a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1421a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1422a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1423f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1424a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1425f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1426a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1427a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1428a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1429a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1430a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1431a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1432a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1433a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1434a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1435a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1436a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1437a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1438a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public boolean isAggregationRequired() { 1439a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return false; 1440a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1441a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1442a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1443a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 14443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 144553056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 14464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private OpenHelper mOpenHelper; 144731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 14484097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1449f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1450f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private HashMap<String, SoftReference<String[]>> mNicknameClusterCache = 1451f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov new HashMap<String, SoftReference<String[]>>(); 1452622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1453622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1454622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1455f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1456a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1457a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 145820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 145920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1460ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 146173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private boolean mImportMode; 146273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1463b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mInsertedRawContacts = Sets.newHashSet(); 1464b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1465b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1466de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 146781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 146881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 1469a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 147053056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 1471a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1472a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1473a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1474a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 1475a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 147653056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 147753056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 1478a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 14794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 14804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 14814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1482de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 148335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1484de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1485de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mOpenHelper = (OpenHelper)getOpenHelper(); 1486a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1487a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mOpenHelper, this, mGlobalSearchSupport); 1488cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov mContactAggregator = new ContactAggregator(this, mOpenHelper, mAggregationScheduler); 14890e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1490a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1491d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 1492653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1493c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1494653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1495653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1496653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1497653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1498653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1499c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1500653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1501653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1502653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1503653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1504653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1505653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1506653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1507653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1508653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1509653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1510653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 15115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mLastTimeContactedUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 15126cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.TIMES_CONTACTED + "=" + RawContacts.TIMES_CONTACTED + "+1," 1513d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + RawContacts.LAST_TIME_CONTACTED + "=? WHERE " + RawContacts.CONTACT_ID + "=?"); 1514a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 151525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate = db.compileStatement( 151625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 151725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " SET " + RawContactsColumns.DISPLAY_NAME + "=?," 151825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov + RawContactsColumns.DISPLAY_NAME_SOURCE + "=?" + 151925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 15203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 152173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 152273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + RawContacts.DIRTY + "=1 WHERE " + RawContacts._ID + "=?"); 152373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1524e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceReplace = db.compileStatement( 1525e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.AGGREGATED_PRESENCE + "(" 1526e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + AggregatedPresenceColumns.CONTACT_ID + ", " 1527e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + Presence.PRESENCE_STATUS 1528e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + ") VALUES (?, (SELECT MAX(" + Presence.PRESENCE_STATUS + ")" 1529e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " FROM " + Tables.PRESENCE + "," + Tables.RAW_CONTACTS 1530a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov + " WHERE " + PresenceColumns.RAW_CONTACT_ID + "=" 1531e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID 1532e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=?))"); 1533e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1534e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceStatusUpdate = db.compileStatement( 1535e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov "UPDATE " + Tables.AGGREGATED_PRESENCE 1536e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " SET " + Presence.PRESENCE_CUSTOM_STATUS + "=? " 1537e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " WHERE " + AggregatedPresenceColumns.CONTACT_ID + "=?"); 1538e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1539622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final Locale locale = Locale.getDefault(); 154028f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 154128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 154228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 154328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 1544622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey context.getString(com.android.internal.R.string.common_name_conjunctions), 1545622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey locale); 1546f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 1547622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mPostalSplitter = new PostalSplitter(locale); 15484097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1549f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1550f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1551f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1552f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1553f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1554f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1555f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 15563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 15573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1558e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 15593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 15603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 156167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 156267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 15633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 15643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 156514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 15663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 15673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1568622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1569622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1570a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1571a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 15723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15733d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1574568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importLegacyContactsAsync(); 15753d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1576568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1577c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov verifyAccounts(); 157870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 15791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 15804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 15814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1582c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 1583c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1584c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1585c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 1586c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 158731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1588de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 158931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov protected OpenHelper getOpenHelper(final Context context) { 159031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov return OpenHelper.getInstance(context); 159131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 159231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1593285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov /* package */ ContactAggregationScheduler getContactAggregationScheduler() { 1594285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mAggregationScheduler; 1595285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1596285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1597013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1598013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1599013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1600013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 16013d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 16023d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 16033d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 16043d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 16053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1606568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1607568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1608568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1609568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1610568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1611568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 1612568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 1613568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1614568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 1615ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 1616568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1617568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 1618568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1619568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 1620568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts()) { 1621568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1622568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* 1623568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * When the import process is done, we can unlock the provider and 1624568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * start aggregating the imported contacts asynchronously. 1625568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1626ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch.countDown(); 1627ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1628568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov scheduleContactAggregation(); 1629568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1630568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1631568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 1632568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1633568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 1634568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1635568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 16363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 1637568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1638568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (importLegacyContacts(importer)) { 16393d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 16403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 16413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 16423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 16433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 16443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 16453d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 16463d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 16473d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 16483d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 16493d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1650568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 16510e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 16523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 165373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = true; 16543d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 16553d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 16560e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(aggregatorEnabled); 16573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 16583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 16593d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 16603d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 166173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } finally { 166273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mImportMode = false; 16633d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 16643d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 16653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1666a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1667a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 1668a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 1669a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 1670a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1671a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1672a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 1673a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1674a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1675a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1676a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1677a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1678a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1679a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mOpenHelper.wipeData(); 1680a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1681a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1682568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1683568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 1684568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1685568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1686568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1687568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1688568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1689568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 1690ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 1691ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 1692ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 1693ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 1694ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 1695ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 1696ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 1697ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 169881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 1699ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1700ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1701568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1702568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1703568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1704568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1705568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1706568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1707568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1708568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1709568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1710568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1711568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1712568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1713568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1714568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1715568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1716568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1717568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 1718568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1719568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1720568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1721568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1722568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1723568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1724568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 1725568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 1726568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1727568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1728568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 17294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1730285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1731bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1732b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1733b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1734285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 17351ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1736b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1737b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1738b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1739b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 1740285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 1741b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 1742df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 1743285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1744285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1745285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1746285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 1747bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1748b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1749b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1750285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1751b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 17521ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 1753b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1754b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1755b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1756bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1757b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1758b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1759b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long rawContactId : mInsertedRawContacts) { 1760b5a4add17815167d20a90645779df34cdf45280dFred Quintana mContactAggregator.insertContact(mDb, rawContactId); 1761285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1762b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1763b5a4add17815167d20a90645779df34cdf45280dFred Quintana String ids; 1764b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 1765b5a4add17815167d20a90645779df34cdf45280dFred Quintana ids = buildIdsString(mUpdatedRawContacts); 1766b5a4add17815167d20a90645779df34cdf45280dFred Quintana mDb.execSQL("UPDATE raw_contacts SET version = version + 1 WHERE _id in " + ids, 1767b5a4add17815167d20a90645779df34cdf45280dFred Quintana new Object[]{}); 1768b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1769b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1770b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 1771b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 1772b5a4add17815167d20a90645779df34cdf45280dFred Quintana mOpenHelper.getSyncState().update(mDb, id, entry.getValue()); 1773b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1774b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1775b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 1776b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1777b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1778b5a4add17815167d20a90645779df34cdf45280dFred Quintana private String buildIdsString(HashSet<Long> ids) { 1779b5a4add17815167d20a90645779df34cdf45280dFred Quintana StringBuilder idsBuilder = null; 1780b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 1781b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (idsBuilder == null) { 1782b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder = new StringBuilder(); 1783b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append("("); 1784b5a4add17815167d20a90645779df34cdf45280dFred Quintana } else { 1785b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(","); 1786b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1787b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(id); 1788b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1789b5a4add17815167d20a90645779df34cdf45280dFred Quintana idsBuilder.append(")"); 1790b5a4add17815167d20a90645779df34cdf45280dFred Quintana return idsBuilder.toString(); 1791285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1792285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1793285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1794cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 179581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 179681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 179781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 179881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 179981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 180081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 180181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 1802cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 1803568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1804568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected void scheduleContactAggregation() { 1805dee54bb86f3608730f0b9f37d8982a7f6b280a85Dmitri Plotnikov mContactAggregator.schedule(); 1806568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1807568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1808285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 1809285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return mInsertedRawContacts.contains(rawContactId); 1810285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1811285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 18123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 18133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 18143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 18153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 18163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 18173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 18183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 18193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 18203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 18214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1822de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 1823bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1824b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "insertInTransaction: " + uri); 1825b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1826f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1827f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 1828f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 1829f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1830a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 1831a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 183235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1833a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 183435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 1835de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov id = mOpenHelper.getSyncState().insert(mDb, values); 183635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 183735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1838d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1839d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 18406bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 18416bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 18426bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 18435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 1844f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 1845d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov id = insertRawContact(values, account); 1846f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1847a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1848a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1849a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 18505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 18515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 1852f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1853f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1854a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1855a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1856a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1857a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 1858f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1859f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1860a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1861a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1862a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1863ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1864ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 1865f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertGroup(values, account, callerIsSyncAdapter); 1866f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1867ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1868ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1869ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1870eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 1871e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey id = insertSettings(values); 187243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 1873eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 1874eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 1875eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 18761f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 18771f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey id = insertPresence(values); 18781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 18791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 18801f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1881a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 188281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 1883f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 1884a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1885a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 18867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 18877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 18887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 18897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1890de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 1891a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1892a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1893a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1894035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 1895035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 1896035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 1897035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 1898035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 18997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 1900035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 1901035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 19026cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME); 19036cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 1904035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 1905035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 1906035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 1907035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 1908035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1909035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 1910035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1911035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 1912df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_NAME, account.name); 1913df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana values.put(RawContacts.ACCOUNT_TYPE, account.type); 1914035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1915035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 19167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 19177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 19187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 1919d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 19206bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 19216bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 19226bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 19236bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1924d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 1925de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 19266bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 19276bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 19286bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 1929a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 1930a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1931a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1932f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 1933a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1934a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1935d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertRawContact(ContentValues values, Account account) { 1936a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 1937d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov overriddenValues.putNull(RawContacts.CONTACT_ID); 1938f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 19397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 19407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 19417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 19423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 19433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 19443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov overriddenValues.put(RawContacts.AGGREGATION_MODE, 19453d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DISABLED); 19463d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19473d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1948023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov long rawContactId = 1949023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, overriddenValues); 1950023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 1951285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1952285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 1953285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.add(rawContactId); 1954023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 1955a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1956a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1957a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1958a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 1959a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1960a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1961a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1962a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1963f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 1964a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 1965de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 1966de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 196767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 1968de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 196920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1970de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 1971de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 1972de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 1973de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 1974de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 1975de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 1976508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 1977de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 1978de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 1979de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 1980de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 1981de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 19824097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1983de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mOpenHelper.getMimeTypeId(mimeType)); 1984de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 1985a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1986a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 1987a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 1988f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1989de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 1990a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1991b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 1992a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1993a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 1994a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 1995a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1996a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 19974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 19984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 19998e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 20008e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 20018e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 20028e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 20038e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 20048e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov int aggregationMode = mOpenHelper.getAggregationMode(rawContactId); 2005f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 20068e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 20078e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 20088e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 20098e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2010421782cb554e5050cf62a86b98df6520038dcd15Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId); 2011f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 20128e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 20138e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 20148e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 20158e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 2016f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 20178e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 20188e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 20198e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2020f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 20218e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2022f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2023c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 20248e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long contactId = mOpenHelper.getContactId(rawContactId); 20258e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2026f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 20278e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2028f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2029f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2030f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2031a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 20325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 20339261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 20349261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 20355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 20369261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 20379261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 20389261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 20399261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 20409261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 20415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId) { 20429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Account account = null; 20436cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts._ID + "=" 20445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId, null, null, null, null); 20459261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 20469261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 204767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountName = c.getString(ContactsQuery.ACCOUNT_NAME); 204867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountType = c.getString(ContactsQuery.ACCOUNT_TYPE); 20499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 20509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana account = new Account(accountName, accountType); 20519261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 20529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 20539261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 20549261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 20559261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 20569261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 20579261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 20589261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "has a sourceid the the contact must be associate with " 20599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 20609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 20619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 20629261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 20635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 20646cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 20659261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2066df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 20679261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 20689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 20699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return c.getLong(0); 20709261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 20719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2072df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2073df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 20749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 20759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 20769261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 20779261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 20789261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 20799261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 20809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return groupId; 20819261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 20829261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 20839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 20849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 20859261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 20869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 20879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 208820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 208920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2090f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 209120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 209220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2093de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2094de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 209514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2096de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2097de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 209814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 209914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2100a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2101a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2102f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 210388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 2104a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2105a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2106a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 210788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 210820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 210920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2110de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 211120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 211220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 211320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 211420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 211520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 211688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 211788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 211888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 211920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2120f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 212188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 212288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 212314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=" + dataId, null, 212414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov null); 2125f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 212620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 212720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 212820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 212920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 213020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 213114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 213220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 213320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 213420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 213520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 213620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 213720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 213820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 213920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 214020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 21417a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 214220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 214320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 214420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2145a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2146a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = rowHandler.delete(mDb, c); 21478e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2148a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2149a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2150a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 21518e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return count; 215220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 215320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 215420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 215520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 215620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 215720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2158ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2159ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2160f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertGroup(ContentValues values, Account account, boolean callerIsSyncAdapter) { 2161ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 2162ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 2163ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 2164ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2165ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2166ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 216767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.RES_PACKAGE); 216867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 216967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.put(GroupsColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 217067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 217167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.remove(Groups.RES_PACKAGE); 2172ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2173f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 217473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov overriddenValues.put(Groups.DIRTY, 1); 217573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 217673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2177ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey long result = mDb.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 2178ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2179ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey if (overriddenValues.containsKey(Groups.GROUP_VISIBLE)) { 2180ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey mOpenHelper.updateAllVisible(); 2181ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2182ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2183ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2184ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2185ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2186e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey private long insertSettings(ContentValues values) { 2187e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 2188e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 2189e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mOpenHelper.updateAllVisible(); 2190e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2191e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2192e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2193e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2194ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 21951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey * Inserts a presence update. 21961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 219770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public long insertPresence(ContentValues values) { 21981f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final String handle = values.getAsString(Presence.IM_HANDLE); 21994dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(handle) || !values.containsKey(Presence.PROTOCOL)) { 22004dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 22014dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 22024dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 22034dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov final long protocol = values.getAsLong(Presence.PROTOCOL); 22044dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 22054dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 22064dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (protocol == Im.PROTOCOL_CUSTOM) { 22074dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov customProtocol = values.getAsString(Presence.CUSTOM_PROTOCOL); 22084dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 22094dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 22104dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 22114dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 22121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 22131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 22141f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // TODO: generalize to allow other providers to match against email 22154dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 22161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 221770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov StringBuilder selection = new StringBuilder(); 22181f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String[] selectionArgs; 22191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (matchEmail) { 22204dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append( 22214dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "((" + MimetypesColumns.MIMETYPE + "='" + Im.CONTENT_ITEM_TYPE + "'" 22224dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.PROTOCOL + "=?" 22234dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.DATA + "=?"); 22244dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (customProtocol != null) { 22254dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 22264dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(selection, customProtocol); 22274dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 22284dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append(") OR (" 22294dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + MimetypesColumns.MIMETYPE + "='" + Email.CONTENT_ITEM_TYPE + "'" 22304dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Email.DATA + "=?" 22314dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + "))"); 22324dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selectionArgs = new String[] { String.valueOf(protocol), handle, handle }; 22331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 22344dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append( 22354dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov MimetypesColumns.MIMETYPE + "='" + Im.CONTENT_ITEM_TYPE + "'" 22364dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.PROTOCOL + "=?" 22374dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov + " AND " + Im.DATA + "=?"); 22384dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (customProtocol != null) { 22394dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selection.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 22404dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(selection, customProtocol); 22414dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 22424dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 22434dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov selectionArgs = new String[] { String.valueOf(protocol), handle }; 22441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 22451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 224670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (values.containsKey(Presence.DATA_ID)) { 224770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.append(" AND " + DataColumns.CONCRETE_ID + "=") 224870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov .append(values.getAsLong(Presence.DATA_ID)); 224970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 225070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 225100ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey selection.append(" AND ").append(getContactsRestrictions()); 225270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 22531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long dataId = -1; 22545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = -1; 2255e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov long contactId = -1; 225670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 22571f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 22581f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2259de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 226070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.toString(), selectionArgs, null, null, null); 22611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 226267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 22635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2264e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 22651f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 22661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 22671f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 22681f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 22691f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 227031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 227131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 227231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 22731f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 22741f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 22751f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey values.put(Presence.DATA_ID, dataId); 22764dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov values.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 22771f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 22781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // Insert the presence update 2279de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long presenceId = mDb.replace(Tables.PRESENCE, null, values); 2280e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 2281e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov if (contactId != -1) { 2282e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov if (values.containsKey(Presence.PRESENCE_STATUS)) { 2283e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceReplace.bindLong(1, contactId); 2284e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceReplace.bindLong(2, contactId); 2285e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceReplace.execute(); 2286e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2287e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov String status = values.getAsString(Presence.PRESENCE_CUSTOM_STATUS); 2288e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov if (status != null) { 2289e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceStatusUpdate.bindString(1, status); 2290e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceStatusUpdate.bindLong(2, contactId); 2291e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mAggregatedPresenceStatusUpdate.execute(); 2292e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2293e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 22941f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return presenceId; 22951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 22961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 22974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2298de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2299bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2300b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2301b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2302b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2303f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2304f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2305508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2306508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 230735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2308de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mOpenHelper.getSyncState().delete(mDb, selection, selectionArgs); 230935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2310b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2311b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2312b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2313b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2314b5a4add17815167d20a90645779df34cdf45280dFred Quintana return mOpenHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2315b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2316cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2317cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2318cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2319cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2320cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2321d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2322d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2323cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 23246bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 23256bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 23262e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 23272e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 23282e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 23292e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 23302e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 23312e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 23322e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 23332e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 23342e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 23352e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 23362e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 23372e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 23382971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 23392971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 23402971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2341e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 23422971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 23432971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 23442971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2345f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana numDeletes += deleteRawContact(rawContactId, callerIsSyncAdapter); 23462971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 23472971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 23482971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 23492971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 23502971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 23512971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 23522971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 23535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 23542971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2355f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteRawContact(rawContactId, callerIsSyncAdapter); 2356508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2357508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 235820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2359f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2360944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2361f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 236220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 236320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 236448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 236548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 236648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 236748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2368508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2369f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2370f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteData(Data._ID + "=" + dataId, null, callerIsSyncAdapter); 2371ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2372ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2373ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2374f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2375f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return deleteGroup(ContentUris.parseId(uri), callerIsSyncAdapter); 23762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 23772971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 23782971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 23792971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 23802971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2381e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 23822971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 23832971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 2384f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana numDeletes += deleteGroup(c.getLong(0), callerIsSyncAdapter); 23852971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 23862971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 23872971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 23882971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 238981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2390f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 239181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 23922971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2393508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2394508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2395eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 239643880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2397e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return deleteSettings(selection, selectionArgs); 2398eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2399eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 24001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 2401eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 24021f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24031f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 240481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 240581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 24063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 240781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2408508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 24094f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 24104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 24112971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana private boolean readBooleanQueryParameter(Uri uri, String name, boolean defaultValue) { 24122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final String flag = uri.getQueryParameter(name); 24132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return flag == null 24142971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana ? defaultValue 24152971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana : (!"false".equals(flag.toLowerCase()) && !"0".equals(flag.toLowerCase())); 241694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 241794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2418f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteGroup(long groupId, boolean callerIsSyncAdapter) { 241994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana final long groupMembershipMimetypeId = mOpenHelper 242094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2421de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 242294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 242394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 242494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 242594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2426f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2427de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 242894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 242994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 243094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2431f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2432de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 243394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 243494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 243594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mOpenHelper.updateAllVisible(); 243694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 243794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 243894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2439e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey private int deleteSettings(String selection, String[] selectionArgs) { 2440e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 2441e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey if (count > 0) { 2442e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mOpenHelper.updateAllVisible(); 2443e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2444e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2445e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2446e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2447cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 2448cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2449cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null); 2450cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2451cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2452cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2453cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 2454cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2455cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2456cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2457cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2458cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2459cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2460cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2461cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2462f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana public int deleteRawContact(long rawContactId, boolean callerIsSyncAdapter) { 2463f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 246414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2465de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 246633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2467a5bfaf55790262eea97de432d9e7f313c219c066Dmitri Plotnikov mOpenHelper.removeContactIfSingleton(rawContactId); 2468cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 246933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 247033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 247133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 2472cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 247381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 247481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 2475cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 2476cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 2477cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2478cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2479cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2480cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2481cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 2482cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2483cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2484f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana private static Account readAccountFromQueryParams(Uri uri) { 24856cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String name = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 24866cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String type = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 2487f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 2488f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana return null; 2489f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana } 2490f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana return new Account(name, type); 2491f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana } 2492f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana 24934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2494de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2495de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 2496bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2497b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2498b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2499b5a4add17815167d20a90645779df34cdf45280dFred Quintana 250035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 250100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 250200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 2503b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 2504b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 2505b5a4add17815167d20a90645779df34cdf45280dFred Quintana Object data = values.get(ContactsContract.SyncStateColumns.DATA); 2506b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 2507b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 2508b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2509b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2510f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2511f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 251200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 251335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2514b5a4add17815167d20a90645779df34cdf45280dFred Quintana return mOpenHelper.getSyncState().update(mDb, values, 2515b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 2516b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2517b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 2518b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 2519b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2520b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2521b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2522b5a4add17815167d20a90645779df34cdf45280dFred Quintana return mOpenHelper.getSyncState().update(mDb, values, 2523b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 2524b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 252535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2526d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 25278c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 252800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 252900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 253000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2531d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 25328c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 2533c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2534c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2535c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 25362e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 25372e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 25382e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 25392e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 25402e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 25412e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 25422e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 25432e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 25442e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 25458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 25462e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 25472e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 25482e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 254920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2550944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2551f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 255281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2553f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 255481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 255520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 255620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2557c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 255848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 255948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 256048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 256148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2562f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 256381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2564f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 256581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 256600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 256700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 25687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 25704529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 25717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 25727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 257533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 25764529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 25774529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=" + rawContactId 25784529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 25794529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 25804529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContact(rawContactId, values); 25814529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 25827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 25837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2585ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2586e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong count = updateGroups(values, appendAccountToSelection(uri, selection), 2587f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 258881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2589f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 259081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2591ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2592ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2593ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2594ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2595ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 259673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov String selectionWithId = (Groups._ID + "=" + groupId + " ") 259773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 2598f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateGroups(values, selectionWithId, selectionArgs, callerIsSyncAdapter); 259981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2600f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 260181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2602ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2603ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2604ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2605127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 2606de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 2607b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2608b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2609b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2610eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 2611e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey count = updateSettings(values, selection, selectionArgs); 261243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2613eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2614eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2615eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 261681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 261781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2618f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 261981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 262000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 262100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 262200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 26234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 26244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2625de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov private int updateGroups(ContentValues values, String selectionWithId, 2626f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 262773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 262873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 2629f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 263073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 263173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 263273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 263373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 263473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 263573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 263673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 263773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2638ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 263994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 264094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana // If changing visibility, then update contacts 2641ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 264294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mOpenHelper.updateAllVisible(); 264394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 264494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 264594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 264694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2647e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey private int updateSettings(ContentValues values, String selection, String[] selectionArgs) { 2648e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 2649e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 2650e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mOpenHelper.updateAllVisible(); 2651e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2652e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2653e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2654e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 26554529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 26564529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 26574529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 26584529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 26594529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 266073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 26614529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 26624529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov Cursor cursor = mDb.query(mOpenHelper.getRawContactView(), 266351bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 26644529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 26654529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 26664529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 26674529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 26684529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 26694529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 26704529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26714529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 26724529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 26734529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26744529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 26754529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 26764529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26774529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 26784529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 26794529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = mDb.update(Tables.RAW_CONTACTS, values, RawContacts._ID + " = " + rawContactId, 26804529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov null); 26815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 2682433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 26834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 2684433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 2685285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 2686285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateLookupKey(mDb, rawContactId); 2687285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 26885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 26895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 269033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 269133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 2692321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 2693f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 269420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 269520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 269620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 26975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 269820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 269920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 270020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 270120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 270220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 270320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 270420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 270520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 270670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 270770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 270820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 270920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 271020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 271170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 271220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 271370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 271420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 271570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 271620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 271770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 271820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 271920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2720653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 272120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2722653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2723653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 272414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 2725653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 2726653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 2727f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 272820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2729653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 2730653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 273120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 273220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2733653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 273420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 273520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2736f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 2737653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 2738653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 2739321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2740653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 274114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 2742a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2743f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana rowHandler.update(mDb, values, c, callerIsSyncAdapter); 27448e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 2745a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 2746a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov triggerAggregation(rawContactId); 2747a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 27488e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2749653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 1; 2750321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2751321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 27528c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 27538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 27548c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 27558c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov Cursor cursor = mDb.query(mOpenHelper.getContactView(), 27568c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 27578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 27588c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 27598c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 27608c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 27618c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 27628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 27638c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 27648c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 27658c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 27668c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 27678c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 27688c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 27698c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 27708c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 27718c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 2772d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 27738c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 27748c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 2775d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 27768c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 2777d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 27788c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 2779d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 27808c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 2781d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 27828c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.STARRED, 2783d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 2784d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2785d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 27868c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 2787d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 2788d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2789d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 27908c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 2791c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 27928c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2793c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 2794c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 27958c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=" + contactId, null); 27968c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 27978c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 27988c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 27998c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 28008c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 28018c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 28028c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 28038c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 28048c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 28058c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 28068c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 28078c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 28088c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov OpenHelper.copyLongValue(mValues, RawContacts.STARRED, 28098c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 28108c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 28118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=" + contactId, null); 2812f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2813d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2814d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public void updateContactTime(long contactId, long lastTimeContacted) { 2815f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 2816d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(2, contactId); 2817f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.execute(); 2818d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2819d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2820127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 2821127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 28220c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 28230c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 282480c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 28250c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 28260c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 28270c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 28280c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 28290c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 28300c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 28310c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 2832b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2833127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 28340c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 28350c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 28360c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=" + rawContactId1 + " AND " 28370c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=" + rawContactId2, null); 28380c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 28396bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 28406bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 28410c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 28420c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 28430c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 28440c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 2845127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2846127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2847dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 2848dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 2849dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 28500c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long contactId1 = mOpenHelper.getContactId(rawContactId1); 28510c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 28520c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 28530c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long contactId2 = mOpenHelper.getContactId(rawContactId2); 28540c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 2855127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2856127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 2857127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 2858127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 2859b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2860b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 286170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 286270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb = mOpenHelper.getWritableDatabase(); 286370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong if (mDb == null) return; 286470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 286570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong Set<Account> validAccounts = Sets.newHashSet(); 286670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accounts) { 286770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong validAccounts.add(new Account(account.name, account.type)); 286870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 286970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong ArrayList<Account> accountsToDelete = new ArrayList<Account>(); 287070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 287170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 287270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 287348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 28745f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana for (String table : new String[]{Tables.RAW_CONTACTS, Tables.GROUPS, Tables.SETTINGS}) { 28755f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // Find all the accounts the contacts DB knows about, mark the ones that aren't 28765f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana // in the valid set for deletion. 28775f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Cursor c = mDb.rawQuery("SELECT DISTINCT account_name, account_type from " 28785f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + table, null); 28795f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana while (c.moveToNext()) { 28805f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (c.getString(0) != null && c.getString(1) != null) { 28815f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Account currAccount = new Account(c.getString(0), c.getString(1)); 28825f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana if (!validAccounts.contains(currAccount)) { 28835f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana accountsToDelete.add(currAccount); 28845f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana } 288570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 288670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 28875f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana c.close(); 288870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 288970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 289070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 28915f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 289270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong String[] params = new String[]{account.name, account.type}; 289370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.GROUPS 289470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 289570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.PRESENCE 289670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (SELECT " 289770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS 289870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?)", params); 289970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.execSQL("DELETE FROM " + Tables.RAW_CONTACTS 290070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong + " WHERE account_name = ? AND account_type = ?", params); 29015f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana mDb.execSQL("DELETE FROM " + Tables.SETTINGS 29025f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana + " WHERE account_name = ? AND account_type = ?", params); 290370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 29044637c20c6b6d3b6f6671e6a44ed57f1e5b9c4484Dmitri Plotnikov mOpenHelper.getSyncState().onAccountsChanged(mDb, accounts); 290570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 290670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 290770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 290870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 290970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 2910619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2911619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 2912622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 2913622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 2914622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private static boolean areAllEmpty(ContentValues values, String[] keys) { 2915622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 2916622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (!TextUtils.isEmpty(values.getAsString(key))) { 2917622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return false; 2918622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 2919622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 2920622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return true; 2921622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 2922622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 29234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 29244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 29254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 2926bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2927bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 2928bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 29290b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 29304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 293135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2932d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 29331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 2934c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 2935c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2936619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 2937619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 2938a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 29394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 294035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 294135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().query(db, projection, selection, selectionArgs, 294235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 294335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2944d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2945ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 2946619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 2947619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2948619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2949d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 29504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2951ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 29524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + contactId); 29536bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 29546bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 29556bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 29565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 29575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 29585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 29595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 29605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 29615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 29625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 29645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 29655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 29665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 29675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov setTablesAndProjectionMapForContacts(lookupQb, projection); 29685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=" + contactId + " AND " + 29695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.LOOKUP_KEY + "="); 29705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov lookupQb.appendWhereEscapeString(lookupKey); 29715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, selectionArgs, sortOrder, 29725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 29735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 29745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 29755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 29785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 29805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 29815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.appendWhere(Contacts._ID + "=" + lookupContactIdByLookupKey(db, lookupKey)); 29825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 29835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 29845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 2985ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 2986ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 2987ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 29884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 29894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 2990e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 29915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 29924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sb.toString()); 2993ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2994ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2995ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2996ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 2997ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 2998ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 29994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3000ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3001d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 30024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 30034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3004e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 30055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 30064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 30074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 30084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3009ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 3010ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 30114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 30124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 30134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3014d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3015d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final String starredQuery = qb.buildQuery(projection, Contacts.STARRED + "=1", 30164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3017d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3018d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3019d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3020ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 30214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 30224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3023d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3024d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String frequentQuery = qb.buildQuery(projection, 3025d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3026d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 30274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3028d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3029d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3030d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3031d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 30324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 30334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3034d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3035d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3036d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3037d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3038d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3039d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3040ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3041ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 3042b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 30434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(sContactsInGroupSelect); 30444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3045b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3046b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3047b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3048b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3049d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 30504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 30514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 30524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 30534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 30544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov appendAccountFromParameter(qb, uri); 30554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 30566bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 30576bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 305800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3059ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 30603653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 30613653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 30623653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 30633653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 30643653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov appendAccountFromParameter(qb, uri); 30653653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=" + contactId); 30663653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 30673653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 30683653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 30693653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 30704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 30714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 30724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 307389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 307489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 30752815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 30762815f58f72f109790585931f601a63ddc02536a5Evan Millar } 30772815f58f72f109790585931f601a63ddc02536a5Evan Millar 307848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 307948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 308048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 308148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov appendAccountFromParameter(qb, uri); 308248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 308348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 308448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 308548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 308648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3087ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 30884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 30895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.setProjectionMap(sDistinctDataProjectionMap); 309089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 309189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3092ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 30934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 30944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 30955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 30965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 30975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 30985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 30995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 31005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 31015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null); 31025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 31035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 31045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 31055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 31065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 31075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 31085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 31095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 31105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 31115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 31125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 31135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 31145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 31155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 31165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 31175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 31185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 31194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(" AND " + sb); 3120ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 31215e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3122ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3123ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3124ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 31264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 31274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 312889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 312989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 31304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 31314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 31324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 313348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 313448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 313548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 313648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov appendAccountFromParameter(qb, uri); 313748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 313848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 313948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 314048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 314148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 31425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 31434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 31444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 314589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 314689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 31474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 31485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + Email.DATA + "="); 31494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhereEscapeString(uri.getLastPathSegment()); 31504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3151ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3152ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3153ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 31545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 31555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 31565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.setProjectionMap(sDistinctDataProjectionMap); 315789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 315889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 31595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 31605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 31615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 31625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("("); 31635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 31645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 31655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 31665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 31675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null); 31685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 31695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 31705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 31715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Email.DATA + " LIKE "); 31721e530df9f7e496dc47f77d4323c89bd413b79b64Dmitri Plotnikov sb.append(DatabaseUtils.sqlEscapeString(filterParam + '%')); 31735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 31745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + sb); 31755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 31765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 31775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 31785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 31795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3180ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 31814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 31824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 318389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 318489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 318589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3186ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3187ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3188ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 318948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 319048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 319148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 319248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov appendAccountFromParameter(qb, uri); 319348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 319448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 319548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + uri.getLastPathSegment()); 319648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 319748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 319848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 31995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 32004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getRawContactView()); 3201d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 320289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 32034f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 32044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 32054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 32065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 32075ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 32084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getRawContactView()); 3209d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 321089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 321189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=" + rawContactId); 32124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 32134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 32144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 32155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 32165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 32174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 32184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 321989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 322089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=" + rawContactId); 3221e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3222e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3223e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 3224e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 32254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 32264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 32274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3228e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3229e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3230e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 32314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 32324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setTables(mOpenHelper.getDataView()); 32334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.setProjectionMap(sDataProjectionMap); 32344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(Data._ID + "=" + ContentUris.parseId(uri)); 32354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 32364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 32374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 3238a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov case DATA_WITH_PRESENCE: { 3239a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov qb.setTables(mOpenHelper.getDataView() + " data" 3240e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE 3241e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " ON (" + AggregatedPresenceColumns.CONTACT_ID + "=" 3242e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 3243a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov qb.setProjectionMap(sDataWithPresenceProjectionMap); 32445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3245a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3246a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3247a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3248a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 32494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3250a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 3251a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 3252a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 3253e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 3254a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3255a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3256e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 3257e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov mOpenHelper.buildPhoneLookupAndContactQuery(qb, number); 3258e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 3259e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 3260e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 3261e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 3262e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 3263a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3264a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3265a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3266ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 326789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(mOpenHelper.getGroupView()); 3268ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 326989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3270ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3271ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3272ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3273ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3274ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 327589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(mOpenHelper.getGroupView()); 3276ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 327789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(Groups._ID + "=" + groupId); 3278ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3279ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3280ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3281ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 328289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(mOpenHelper.getGroupView() + " AS groups"); 3283ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 328489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 328589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 3286ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3287ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3288ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3289b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 32900c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 3291b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 3292b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3293b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3294b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 329531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 3296d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 32972d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 32982d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 32992d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 33002d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 330131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 3302d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 3303d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 330431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 330531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 330631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 330731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 33087581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, projection); 33097581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 33107581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 33112d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 331231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 331331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3314eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3315eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 3316eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 331789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3318e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3319e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 3320e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 3321e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final String groupMembershipMimetypeId = Long.toString(mOpenHelper 3322e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 3323ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (mOpenHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3324e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3325e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3326ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (mOpenHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3327e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3328e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3329e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3330eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3331eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3332eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 33335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case PRESENCE: { 3334373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setTables(Tables.PRESENCE); 3335373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setProjectionMap(sPresenceProjectionMap); 33365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 33375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 33385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 33395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case PRESENCE_ID: { 3340373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setTables(Tables.PRESENCE); 3341373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setProjectionMap(sPresenceProjectionMap); 3342373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.appendWhere(Presence._ID + "=" + ContentUris.parseId(uri)); 33435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 33445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 33455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 3346c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 3347a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 3348c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3349c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3350c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 3351b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3352b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh(db, contactId, projection); 3353c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3354c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 33551b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 33561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 33571b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 33581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 33591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 33601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 33611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 33621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 33631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 33641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 33651b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 33661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 33671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 33681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 33691b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 33701b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 33711b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 33721b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 33731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mOpenHelper.getContactView()); 33741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 33751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(sContactsInGroupSelect); 33761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 33771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 33781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 33794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 3380f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 3381c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 33824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 33834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 33845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 33855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 33875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 33885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 33895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 3390038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 3391038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 3392038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 3393038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 33945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 33955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 33964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 33974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 33984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 33994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 34004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 34014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 34025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 34035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 34045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 34055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 34075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (contactId == -1) { 34085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 34095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 34125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 34155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 34165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 34185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 34195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 34205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 34215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 34225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 34235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 34255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 34265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 34275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 34285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 34315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 34325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int sourceIdCount = 0; 34335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 34345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 34355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 34365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sourceIdCount++; 34375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (sourceIdCount == 0) { 34415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 34425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 34455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 34465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 34475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 34485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 34495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup) { 34505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 34515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 34525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 34555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 34565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 34585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 34595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 34605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 34615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 34625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 34635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 34645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 34655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 34665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 34675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 34685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 34695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 34705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 34715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 34725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 34765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 34775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 34805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupByDisplayNameQuery { 34835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 34845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 34865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 34875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 34885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 34895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 34905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 34915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 34935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 34945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 34955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int NORMALIZED_NAME = 3; 34965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 34985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 34995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 35005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int displayNameCount = 0; 35015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 35025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 35035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 35045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov displayNameCount++; 35055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 35095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 35105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // First try sync ids 35135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 35145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 35155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 35165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 35175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup) { 35185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 35195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 35205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 35235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 35245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 35255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 35275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 35285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 35295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 35305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 35315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 35325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 35335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 35345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 35355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 35365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 35375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 35385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 35395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 35405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 35415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 35455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 35465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 35495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 35525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 35535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 35545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 35555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 35565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 35585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 35595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 35615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 35625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 35635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 35645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 35655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 35665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 35675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 35685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 35695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 35705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 35715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 35725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 35735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 35755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 35765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 35805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 35815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 35825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 35835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 35855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3586ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, String[] projection) { 3587ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov String contactView = mOpenHelper.getContactView(); 3588ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov boolean needsPresence = mOpenHelper.isInProjection(projection, Contacts.PRESENCE_STATUS, 3589ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Contacts.PRESENCE_CUSTOM_STATUS); 3590ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (!needsPresence) { 3591ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setTables(contactView); 3592ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 3593ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } else { 3594ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setTables(contactView + " LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + " ON (" 3595ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ") "); 3596ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov qb.setProjectionMap(sContactsWithPresenceProjectionMap); 3597ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 3598ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 3599ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 3600ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 36014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 36024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 36034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 36044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 36054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 36064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 36074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 36084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 36094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 36104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 36114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 36124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 36134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3614e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 3615e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 3616e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 3617e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(accountName)) { 3618e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 3619e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 3620e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 3621e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 3622e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 3623e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 3624e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 3625e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 3626e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3627e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 3628e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 3629e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 3630e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3631e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 3632e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 36337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 3634c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 3635c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 3636c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 3637c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 3638c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 3639c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private String getLimit(Uri url) { 3640c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limitParam = url.getQueryParameter("limit"); 3641c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 3642c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3643c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3644c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 3645c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 3646c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 3647c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 3648c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 3649c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3650c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3651c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 3652c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 3653c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 3654c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 3655c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3656c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3657c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 36585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 36595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 36605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 36615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 36625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 36635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 36645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 36655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 36665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 36675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 36685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 36695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 36705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 36725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 36735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 36745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 36765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 36775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 36795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 36805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 36825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 36835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 36855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 36865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 368800ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 36894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (mOpenHelper.hasRestrictedAccess()) { 369070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 369170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 36926cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 369370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 369470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 369570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 369670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 36974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (mOpenHelper.hasRestrictedAccess()) { 369870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 369967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 37005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 37015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 3702619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3703619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3704619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3705b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 3706b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 3707b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 3708b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 3709d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 3710b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov if (!"r".equals(mode)) { 3711b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 3712b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3713b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3714b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 3715b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3716b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov String sql = 3717b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mOpenHelper.getDataView() + 3718b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 3719b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=" + contactId; 3720b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 3721b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, null); 3722d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3723d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3724d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_LOOKUP: 3725d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_LOOKUP_ID: { 3726d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // TODO: optimize lookup when direct id provided 3727d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String lookupKey = uri.getPathSegments().get(2); 3728d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 3729d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final String selection = RawContacts.CONTACT_ID + "=" + contactId; 3730d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3731d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 3732d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 3733d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 3734d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 3735d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey outputRawContactsAsVCard(localStream, selection, null); 3736d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 3737d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3738b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3739b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 3740b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov throw new FileNotFoundException("No file at: " + uri); 3741b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3742b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 3743b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3744d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 3745d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String VCARD_TYPE_DEFAULT = "default"; 3746d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3747d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 3748d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 3749d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 3750d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 3751d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 3752d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 3753d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 3754d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 3755d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3756d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 3757d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 3758d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3759d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 3760d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 3761d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 3762b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3763d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 3764d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 3765d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 3766d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3767d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 3768d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3769d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3770d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 3771d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 3772d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 3773d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 3774d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 3775d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 3776d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 3777d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 3778d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final VCardComposer composer = new VCardComposer(context, VCARD_TYPE_DEFAULT, false); 3779d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 3780d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3781d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // TODO: enforce the callers security clause is used 3782d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.init(selection, selectionArgs)) 3783d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 3784d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 3785d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 3786d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 3787d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 3788d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3789d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3790d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 3791d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 3792b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 3793619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 37947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 37957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 37967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 3797d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static class RawContactsEntityIterator implements EntityIterator { 37987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 37997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 38007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 38017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 38027a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 38037a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 38047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 38057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 38067a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 38077a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 38087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 38097a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 38107a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 38117a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 38127a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 38137a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 38147a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 38157a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 38167a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 38177a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 38187a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 38197a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 38207a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4}; 38217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 38227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] PROJECTION = new String[]{ 38236cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 38246cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 38256cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.SOURCE_ID, 38266cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.VERSION, 38276cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.DIRTY, 38287a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data._ID, 38297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RES_PACKAGE, 38307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.MIMETYPE, 38317a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 38327a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 38337a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 38347a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 38357a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 38367a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 38377a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 38387a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 38397a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 38407a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 38417a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 38427a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 38437a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 38447a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 38457a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 38467a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 38477a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 38487a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 38497a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4, 38507a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RAW_CONTACT_ID, 38517a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.IS_PRIMARY, 38523cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar Data.IS_SUPER_PRIMARY, 38537a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA_VERSION, 38547a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana GroupMembership.GROUP_SOURCE_ID, 38557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC1, 38567a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC2, 38577a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC3, 385894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana RawContacts.SYNC4, 385938446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey RawContacts.DELETED, 3860c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.CONTACT_ID, 3861c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey RawContacts.STARRED}; 3862035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 3863035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 3864035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 3865035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 3866035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 3867035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 3868035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 386967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_RES_PACKAGE = 6; 387067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_MIMETYPE = 7; 387167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA1 = 8; 38727a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_RAW_CONTACT_ID = 27; 38737a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_IS_PRIMARY = 28; 38743cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_IS_SUPER_PRIMARY = 29; 38753cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DATA_VERSION = 30; 38763cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_GROUP_SOURCE_ID = 31; 38773cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC1 = 32; 38783cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC2 = 33; 38793cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC3 = 34; 38803cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_SYNC4 = 35; 38813cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_DELETED = 36; 38823cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_CONTACT_ID = 37; 38833cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar private static final int COLUMN_STARRED = 38; 38847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3885d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey public RawContactsEntityIterator(ContactsProvider2 provider, String contactsIdString, Uri uri, 38867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 38877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 38887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 38897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final String updatedSortOrder = (sortOrder == null) 38907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana ? Data.RAW_CONTACT_ID 38917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana : (Data.RAW_CONTACT_ID + "," + sortOrder); 38927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 38937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 38947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 3895226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setTables(Tables.CONTACT_ENTITIES); 38967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 38975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.appendWhere(Data.RAW_CONTACT_ID + "=" + contactsIdString); 38987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 38996cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 39006cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 3901035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName)) { 39026cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 3903035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 39046cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 3905035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 3906035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 39077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 39087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana null, null, updatedSortOrder); 39097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 39107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3912038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 3913038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 3914038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 3915038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 3916038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 3917038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 3918038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana 39197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 39207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 39217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 39227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 39247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 39257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 39287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 39297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 39307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 39337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 39367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 39377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 39387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 39407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 39417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 39447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39457a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final long rawContactId = c.getLong(COLUMN_RAW_CONTACT_ID); 39467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 39487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 39496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 39506cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 39515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 39526cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 39536cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 39546cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 39557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC1, c.getString(COLUMN_SYNC1)); 39567a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC2, c.getString(COLUMN_SYNC2)); 39577a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC3, c.getString(COLUMN_SYNC3)); 39587a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC4, c.getString(COLUMN_SYNC4)); 395994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana contactValues.put(RawContacts.DELETED, c.getLong(COLUMN_DELETED)); 396038446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey contactValues.put(RawContacts.CONTACT_ID, c.getLong(COLUMN_CONTACT_ID)); 3961c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey contactValues.put(RawContacts.STARRED, c.getLong(COLUMN_STARRED)); 39627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 39637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 39657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 39667a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana if (rawContactId != c.getLong(COLUMN_RAW_CONTACT_ID)) { 39677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 39687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 39707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 39717a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data._ID, c.getString(COLUMN_DATA_ID)); 39727a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 39737a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 39747a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.IS_PRIMARY, c.getString(COLUMN_IS_PRIMARY)); 39753cb415e7b97c3e318d7a16aaf7cc5c6b825d349aEvan Millar dataValues.put(Data.IS_SUPER_PRIMARY, c.getString(COLUMN_IS_SUPER_PRIMARY)); 39767a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 39779261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 39789261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana dataValues.put(GroupMembership.GROUP_SOURCE_ID, 39799261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.getString(COLUMN_GROUP_SOURCE_ID)); 39809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 39817a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 39827a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana for (int i = 0; i < DATA_KEYS.length; i++) { 39837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 39847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 39857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 39867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 39877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 39887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 39897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 39907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 39917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 39927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 39937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 39947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 39957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 39987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 39997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 40007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 40017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 40037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4004226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana /** 4005226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 4006226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 4007226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana */ 4008226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static class GroupsEntityIterator implements EntityIterator { 4009226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private final Cursor mEntityCursor; 4010226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private volatile boolean mIsClosed; 4011226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4012226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final String[] PROJECTION = new String[]{ 4013226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups._ID, 4014226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_NAME, 4015226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_TYPE, 4016226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.SOURCE_ID, 4017226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.DIRTY, 4018226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.VERSION, 4019226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.RES_PACKAGE, 4020226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE, 4021226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE_RES, 40227a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.GROUP_VISIBLE, 40237a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC1, 40247a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC2, 40257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC3, 40267a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC4, 40277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYSTEM_ID, 402894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.NOTES, 402994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana Groups.DELETED}; 4030226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4031226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ID = 0; 4032226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_NAME = 1; 4033226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_TYPE = 2; 4034226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_SOURCE_ID = 3; 4035226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_DIRTY = 4; 4036226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_VERSION = 5; 4037226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_RES_PACKAGE = 6; 4038226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE = 7; 4039226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE_RES = 8; 4040226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_GROUP_VISIBLE = 9; 40417a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 10; 40427a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 11; 40437a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 12; 40447a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 13; 40457a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYSTEM_ID = 14; 40467a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_NOTES = 15; 404794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana private static final int COLUMN_DELETED = 16; 4048226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4049226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 4050226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 4051226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = false; 4052226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4053226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String updatedSortOrder = (sortOrder == null) 4054226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ? Groups._ID 4055226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana : (Groups._ID + "," + sortOrder); 4056226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4057226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 4058226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 405989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.setTables(provider.mOpenHelper.getGroupView()); 4060226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setProjectionMap(sGroupsProjectionMap); 4061226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (groupIdString != null) { 4062226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups._ID + "=" + groupIdString); 4063226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4064226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountName = uri.getQueryParameter(Groups.ACCOUNT_NAME); 4065226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountType = uri.getQueryParameter(Groups.ACCOUNT_TYPE); 4066226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!TextUtils.isEmpty(accountName)) { 4067226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups.ACCOUNT_NAME + "=" 4068226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4069226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + Groups.ACCOUNT_TYPE + "=" 4070226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 4071226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4072226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 4073226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana null, null, updatedSortOrder); 4074226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToFirst(); 4075226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4076226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4077226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public void close() { 4078226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4079226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("closing when already closed"); 4080226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4081226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = true; 4082226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.close(); 4083226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4084226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4085226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public boolean hasNext() throws RemoteException { 4086226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4087226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 4088226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4089226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4090226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return !mEntityCursor.isAfterLast(); 4091226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4092226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4093038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana public void reset() throws RemoteException { 4094038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (mIsClosed) { 4095038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana throw new IllegalStateException("calling reset() when the iterator is closed"); 4096038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4097038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana mEntityCursor.moveToFirst(); 4098038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 4099e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 4100226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public Entity next() throws RemoteException { 4101226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 4102226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 4103226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4104226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!hasNext()) { 4105226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 4106226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4107226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4108226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 4109226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4110226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final long groupId = c.getLong(COLUMN_ID); 4111226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4112226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana // we expect the cursor is already at the row we need to read from 4113226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ContentValues groupValues = new ContentValues(); 4114226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 4115226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 4116226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups._ID, groupId); 4117226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 4118226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 4119226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 4120226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 4121226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 4122226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 4123226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 41247a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC1, c.getString(COLUMN_SYNC1)); 41257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC2, c.getString(COLUMN_SYNC2)); 41267a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC3, c.getString(COLUMN_SYNC3)); 41277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC4, c.getString(COLUMN_SYNC4)); 41287a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYSTEM_ID, c.getString(COLUMN_SYSTEM_ID)); 412994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana groupValues.put(Groups.DELETED, c.getLong(COLUMN_DELETED)); 41307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.NOTES, c.getString(COLUMN_NOTES)); 4131226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Entity group = new Entity(groupValues); 4132226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4133226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToNext(); 4134226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4135226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return group; 4136226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4137226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4138226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4139a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 41407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 41417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 4142568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 4143568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 41447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 41457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 41465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: 41475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: 41487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 41495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (match == RAW_CONTACTS_ID) { 41507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 41517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4153d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return new RawContactsEntityIterator(this, contactsIdString, 41547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana uri, selection, selectionArgs, sortOrder); 4155226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS: 4156226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS_ID: 4157226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String idString = null; 4158226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (match == GROUPS_ID) { 4159226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana idString = uri.getPathSegments().get(1); 4160226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 4161226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 4162226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return new GroupsEntityIterator(this, idString, 4163226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana uri, selection, selectionArgs, sortOrder); 41647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 41657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 41667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 41687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 41694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 41704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4171a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 41724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4173b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4174b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP: 4175be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 4176b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4177b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4178b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4179b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4180be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4181b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4182b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4183508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4184b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return mOpenHelper.getDataMimeType(ContentUris.parseId(uri)); 418548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 418648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 418748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 418848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 418948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 419048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 419148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 419248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 419348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 419448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 419548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 419648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4197b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4198b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4199b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4200b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4201b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4202b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4203b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4204b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4205c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4206c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4207c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4208c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 420961efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 421061efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 42114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 42124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 42137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 421425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private void setDisplayName(long rawContactId, String displayName, int bestDisplayNameSource) { 42153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 421625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindString(1, displayName); 42173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 421825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindNull(1); 42193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 422025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(2, bestDisplayNameSource); 422125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(3, rawContactId); 422225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 42233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 42243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 422573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 422673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 422773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 422873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 422973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.bindLong(1, rawContactId); 423073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mRawContactDirtyUpdate.execute(); 423173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 423273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4233c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4234c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 4235c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 4236c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4237c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4238c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4239653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 4240c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 4241653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 4242653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 4243c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 4244c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4245c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 4246c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 4247c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 4248c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 4249c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 4250c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 4251c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 4252653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 4253c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 4254653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 4255653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 4256c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 4257c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 4258ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4259f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 4260f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 4261f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4262f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4263f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4264f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); 4265f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (tokens.length == 0) { 4266f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4267f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4268f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4269f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String address = tokens[0].getAddress(); 4270f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int at = address.indexOf('@'); 4271f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (at != -1) { 4272f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov address = address.substring(0, at); 4273f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4274f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4275f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4276f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 4277f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4278f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4279f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4280f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 4281f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4282f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 4283f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 4284f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 4285f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4286f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4287f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 4288f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 4289f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4290f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4291f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4292f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name) { 4293f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name); 4294f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4295f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4296f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4297f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Returns nickname cluster IDs or null. Maintains cache. 4298f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4299f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4300f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SoftReference<String[]> ref; 4301f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4302f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4303f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (mNicknameClusterCache.containsKey(normalizedName)) { 4304f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = mNicknameClusterCache.get(normalizedName); 4305f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (ref == null) { 4306f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return null; 4307f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4308f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = ref.get(); 4309f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4310f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4311f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4312f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (clusters == null) { 4313f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = loadNicknameClusters(normalizedName); 4314f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ref = clusters == null ? null : new SoftReference<String[]>(clusters); 4315f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov synchronized (mNicknameClusterCache) { 4316f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNicknameClusterCache.put(normalizedName, ref); 4317f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4318f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4319f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4320f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4321f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4322f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] loadNicknameClusters(String normalizedName) { 4323f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 4324f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String[] clusters = null; 4325f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupQuery.TABLE, NicknameLookupQuery.COLUMNS, 4326f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupColumns.NAME + "=?", new String[] { normalizedName }, 4327f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov null, null, null); 4328f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov try { 4329f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int count = cursor.getCount(); 4330f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (count > 0) { 4331f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters = new String[count]; 4332f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov for (int i = 0; i < count; i++) { 4333f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.moveToNext(); 4334f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov clusters[i] = cursor.getString(NicknameLookupQuery.CLUSTER); 4335f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4336f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4337f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } finally { 4338f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov cursor.close(); 4339f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4340f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return clusters; 4341f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4342f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4343f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 4344f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4345f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 4346f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 4347f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4348f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4349f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4350f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 4351f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 4352f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 4353f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4354f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4355f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4356f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4357f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return ContactsProvider2.this.getCommonNicknameClusters(normalizedName); 4358f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4359f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4360f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4361f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4362f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 4363f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4364f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 4365f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 1, rawContactId); 4366f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 2, dataId); 4367f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 3, lookupType); 4368f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 4, name); 4369f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 4370f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4371f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4372f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 4373f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 4374f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 4375f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 4376f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupDelete, 1, dataId); 4377f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 4378f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4379f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 43802d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 4381e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append("(SELECT DISTINCT " + RawContacts.CONTACT_ID + " FROM " + Tables.RAW_CONTACTS 4382e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " JOIN name_lookup ON(" + RawContactsColumns.CONCRETE_ID + "=raw_contact_id)" 4383e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov + " WHERE normalized_name GLOB '"); 4384e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 43853de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov sb.append("*' AND (" 43863de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 43873de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov + " OR " 43883de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NICKNAME + "))"); 4389e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 4390e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 43915ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 4392c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4393c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 4394c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 4395c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4396c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4397a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 4398c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit) { 43995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), limit); 44005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 44025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 44035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String limit) { 4404c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append("(SELECT DISTINCT raw_contact_id FROM name_lookup WHERE normalized_name GLOB '"); 44055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 44063de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov sb.append("*' AND (" 44073de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 44083de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov + " OR " 44093de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NICKNAME + ")"); 44103de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 4411c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limit != null) { 4412c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(" LIMIT ").append(limit); 4413c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4414c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(")"); 4415ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4416ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 44174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 44184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 44194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 44204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 4421b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 4422b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 4423b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 4424b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 4425b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 44264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 44274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 4428b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 4429b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4430b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4431caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 4432caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 4433caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 4434caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 4435df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 4436df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 4437caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 4438caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 4439caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 4440caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 44416f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 4442caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 44436f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 4444caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 44454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 4446