ContactsProvider2.java revision bc487a312a84972f03776cdc5784cc132a57f8fd
14f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/* 24f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Copyright (C) 2009 The Android Open Source Project 34f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 44f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 54f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * you may not use this file except in compliance with the License. 64f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * You may obtain a copy of the License at 74f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 84f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 94f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Unless required by applicable law or agreed to in writing, software 114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * See the License for the specific language governing permissions and 144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * limitations under the License 154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts; 1828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar 193de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.internal.content.SyncStateContentProviderHelper; 203de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 21b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 22b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 23b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 24b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkeyimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 26b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 27b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 28b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 29b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 30b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 31b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 32b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 33b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 34b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 35b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 36b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 37b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 38a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Lists; 39a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Maps; 40a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Sets; 413de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 42b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 43caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 445b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 45bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.Notification; 46bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.NotificationManager; 47bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.PendingIntent; 48c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 49568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 50568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 516ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 5235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 55627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.IContentService; 56bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.content.Intent; 57568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 59627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 6067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 613de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.content.SharedPreferences.Editor; 62b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 634cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Taoimport android.content.res.Configuration; 641129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikovimport android.database.CharArrayBuffer; 654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 66ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.CursorWrapper; 67ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 6809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor; 6909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor.RowBuilder; 70a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 71b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 74c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 7651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikovimport android.os.AsyncTask; 776ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 78d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 79b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 800e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 81d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 827a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawaimport android.pim.vcard.VCardConfig; 833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 84508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 853de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 863de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.LiveFolders; 873de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.OpenableColumns; 883de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.SyncStateContract; 89b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 90ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 913de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 923de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.DisplayNameSources; 945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.FullNameStyle; 953de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 96bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.provider.ContactsContract.Intents; 973de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.PhoneticNameStyle; 9909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 1003de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 101916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 1023de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 10382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 1043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 105ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 106ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 1073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 1083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 1093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 110de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 111b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 1124097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 11367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 114a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 115a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 116c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 118d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 119b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 120d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 121d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 12242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.text.SimpleDateFormat; 1237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 12542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.util.Date; 126b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1270e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 129622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 130b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1310e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 132ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1385b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 139caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 140bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 141bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 142bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 144619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 145619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 146619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 151b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov * Property key for the legacy contact import version. The need for a version 1523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1533d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1543d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 155b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final String PROPERTY_CONTACTS_IMPORTED = "contacts_imported_v1"; 156b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int PROPERTY_CONTACTS_IMPORT_VERSION = 1; 15751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final String PREF_LOCALE = "locale"; 1583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1590e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1600e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 161a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1635e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final String TIMES_CONTACED_SORT_COLUMN = "times_contacted_sort"; 1645e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 165d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 1665e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar + TIMES_CONTACED_SORT_COLUMN + " DESC, " 1679b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 168d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 169d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 170d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 171d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1726e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 1739b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 1749b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1759b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 1769b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 1776e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 1789b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 1799b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1809b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 1819b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 182de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 183de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 184d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 185d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 194f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 19542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann private static final int CONTACTS_AS_MULTI_VCARD = 1011; 1964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 20046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 2014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2026bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2036bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 204ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 20548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 20648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 20748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 20848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 20948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 21048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 21148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 21248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 213a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2146bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 2156bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 216b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 217b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 218b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 21982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 22082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 2211f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 22231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 22331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 224eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 225eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 226ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 227ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 228ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 229ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 23035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 231b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 23235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 233c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 234c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 235c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2361b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2371b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2381b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2391b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2401b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 24146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 24246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 24309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 24409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 245d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 246f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 247f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 248f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 24967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 25067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 253f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 254ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 255ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 256d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 25767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 258d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 259ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 26114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 26267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 269f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 27088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 27188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 27288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 27388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 27488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 27588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 27688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 277f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 2783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 28014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 284f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 2853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 28714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 288321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 28920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 29020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 291321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 292321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 29320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 29420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 295f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 29619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 29719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 29819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 29919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 300ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 301ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 302ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 30319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 30419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 30519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 306ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 307ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 30819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 30919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 310c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 311df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 312caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 31371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 31471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 31571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 31671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 31771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 31871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 31971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 32071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 32171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 32271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 32371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 32471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 32571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 32671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 327a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 328a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 329a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 330a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 331a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 332a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 333a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 334a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 335a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 336a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 337a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 338a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 339916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 340916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 341916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 342916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 343916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NICKNAME + "," + 344916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_SHORTHAND + "," + 345f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.ORGANIZATION + "," + 346f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.NAME_CONSONANTS; 347916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 348916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 349038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 350038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 351e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 353916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 354916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final HashMap<String, String> sContactsProjectionWithSnippetMap; 355916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 3565e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 3575e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentStarredProjectionMap; 3585e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentFrequentProjectionMap; 359f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 360f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final HashMap<String, String> sContactsVCardProjectionMap; 361ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 362d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 36346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** Contains the columns from the raw contacts entity view*/ 36446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final HashMap<String, String> sRawContactsEntityProjectionMap; 3654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 370e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 371ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 372ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 373ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 374ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 375373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 376b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 377eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 378eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 37982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 38082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 3811b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3821b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 3859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 3869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 3879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 3889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 3899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 3902526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 3912526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 392bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 393bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 394bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 395bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 39651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 397c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 398c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 400c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 4013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 40225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 40382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 404a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 405f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 406f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 407a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 408a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 409a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 4100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 411a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 412f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov private SQLiteStatement mResetNameVerifiedForOtherRawContacts; 413a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 414f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 415f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 4161129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdStructuredName; 4171129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdOrganization; 4181129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdNickname; 4191129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdPhone; 420f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 4211129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 4221129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 4232526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 4242526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 425f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 426f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 4274f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 4284f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 429a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 430d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 431d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 432d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 4333653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 4343653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 4352d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 4362d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 4373653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 4385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 4395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 4405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 441f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 44242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 44342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 4445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 445ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 446ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 4475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 4483653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 45246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 45346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 45446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 455b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 458ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 45948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 461ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 46348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 467ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 46848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4691f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 470ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 471ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 472ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 473ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 47435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 475b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 476b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 47735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 478a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 479b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 480b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 481b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 482b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 484eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 485eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 48682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 48782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 4881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 489c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 490c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 491c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 492c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 4932d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 494c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 495c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4961b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 4971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 4981b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 4991b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 5001b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 5011b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 5021b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 5031b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 50409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 50509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 50619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 50719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 50819a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 509038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 510038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 511e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 5124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 5134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 5145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME_PRIMARY); 5155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 5165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 5175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 5185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 5195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 5205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 5215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, Contacts.SORT_KEY_ALTERNATIVE); 5224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 5264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 5274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 528f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 5294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 531f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 5323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 5333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 5343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 5353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 5363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 5373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 5383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 5393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 5403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 5413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 5423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 5433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 5443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 5453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 546916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap = new HashMap<String, String>(); 547916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.putAll(sContactsProjectionMap); 548916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_MIMETYPE, 549916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov SearchSnippetColumns.SNIPPET_MIMETYPE); 550916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA_ID, 551916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA_ID); 5529c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA1, 5539c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA1); 5549c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA2, 5559c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA2); 5569c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA3, 5579c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA3); 5589c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA4, 5599c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA4); 560916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5615e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5625e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5635e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Long.MAX_VALUE + " AS " + TIMES_CONTACED_SORT_COLUMN); 5645e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5655e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5665e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5675e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Contacts.TIMES_CONTACTED + " AS " + TIMES_CONTACED_SORT_COLUMN); 5685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 569f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap = Maps.newHashMap(); 570f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 571d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 572ba355248c255551bc65d8023b968513cbe9bcdf3Jeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "NULL AS " + OpenableColumns.SIZE); 5734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 5754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 5764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 5824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 5835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_PRIMARY, 5845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY); 5855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, 5865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE); 5875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_SOURCE, 5885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE); 5895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.PHONETIC_NAME, 5905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME); 5915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.PHONETIC_NAME_STYLE, 5925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE); 593f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.NAME_VERIFIED, 594f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov RawContacts.NAME_VERIFIED); 5955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SORT_KEY_PRIMARY, 5965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY); 5975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SORT_KEY_ALTERNATIVE, 5985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE); 5994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 6004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 6014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 6024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 6034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 6044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 6054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 6064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 6074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 6084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 6094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 6102815f58f72f109790585931f601a63ddc02536a5Evan Millar 6114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 6124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 6134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 6144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 6154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 6164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 6174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 6184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 6194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 6204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 6214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 6224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 6234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 6244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 6254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 6264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 6274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 6284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 6294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 6304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 6314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 6324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 6334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 6344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 6354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 6364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 6374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 63882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 6394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 6404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 6414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 6424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 6434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 644f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov sDataProjectionMap.put(RawContacts.NAME_VERIFIED, RawContacts.NAME_VERIFIED); 64556d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 6464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 6475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 6485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 6495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 6505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 6515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 6525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 6535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, Contacts.SORT_KEY_ALTERNATIVE); 6544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 6554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 6564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 6574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 6584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 6594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 660a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 6614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 662a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 66346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana HashMap<String, String> columns; 66446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns = new HashMap<String, String>(); 66546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts._ID, RawContacts._ID); 66646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 66746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 66846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 66946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 67046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.VERSION, RawContacts.VERSION); 67146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 67246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DELETED, RawContacts.DELETED); 673bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey columns.put(RawContacts.IS_RESTRICTED, RawContacts.IS_RESTRICTED); 67446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 67546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 67646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 67746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 678f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov columns.put(RawContacts.NAME_VERIFIED, RawContacts.NAME_VERIFIED); 67946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 68046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.MIMETYPE, Data.MIMETYPE); 68146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA1, Data.DATA1); 68246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA2, Data.DATA2); 68346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA3, Data.DATA3); 68446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA4, Data.DATA4); 68546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA5, Data.DATA5); 68646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA6, Data.DATA6); 68746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA7, Data.DATA7); 68846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA8, Data.DATA8); 68946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA9, Data.DATA9); 69046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA10, Data.DATA10); 69146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA11, Data.DATA11); 69246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA12, Data.DATA12); 69346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA13, Data.DATA13); 69446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA14, Data.DATA14); 69546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA15, Data.DATA15); 69646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC1, Data.SYNC1); 69746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC2, Data.SYNC2); 69846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC3, Data.SYNC3); 69946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC4, Data.SYNC4); 70046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 70146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.STARRED, Data.STARRED); 70246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 70346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 70446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 70546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 70646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana sRawContactsEntityProjectionMap = columns; 70746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 7083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 7093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 7103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 7113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 7123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 7133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 7143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 7163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 7183296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7193296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 7203296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 7213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 7233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.PRESENCE, 7243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 7253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS, 7263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 7273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 7283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 7303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_LABEL, 7323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_ICON, 7343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 7353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 7375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 7385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 7395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 7405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 7415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 7425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 7435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 7445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 7455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 7465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 7475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 7485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 7495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 7505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 7515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 7525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 7535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 7545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 7555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 7565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 7575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 7585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 7595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 7605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 7615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 7625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 7635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 7645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 7658f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 7665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 7675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 7685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 7695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 7705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 7715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 7725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 7735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, 7745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.SORT_KEY_ALTERNATIVE); 7755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 7765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 7775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 7785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 7795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 7805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 781a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 7825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 7835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 7845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 7853296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 7863296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 7873296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 7883296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 7893296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 7903296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 7913296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7923296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 7933296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7943296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 7953296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 7973296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 7983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 8003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 8013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 8023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS, 8033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 8043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 8053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 8063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 8073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 8083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 8093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 8103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 8113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 8123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 813e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 814e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 815fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts._ID 816fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup._ID); 81756d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 818fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LOOKUP_KEY 819fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.LOOKUP_KEY); 820e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 821fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.DISPLAY_NAME 822fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.DISPLAY_NAME); 823e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 824fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LAST_TIME_CONTACTED 825e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 826e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 827fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.TIMES_CONTACTED 828fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.TIMES_CONTACTED); 829e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 830fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.STARRED 831fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.STARRED); 832e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 833fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.IN_VISIBLE_GROUP 834fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 835e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 836fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.PHOTO_ID 837fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.PHOTO_ID); 838e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 839fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.CUSTOM_RINGTONE 840fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.CUSTOM_RINGTONE); 841e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 842fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.HAS_PHONE_NUMBER 843fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 844e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 845fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.SEND_TO_VOICEMAIL 846e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 847e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 848e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 849e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 850e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 851e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 852e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 8539261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 854ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 855ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 85689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 857035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 858035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 8599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 8609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 8619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 86289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 863ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 86467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 865ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 8663cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 86794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 8683cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 86938446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 87089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 87189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 87289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 87389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 874ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 875ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 8766cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 877ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 878ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 879d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 880d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 881ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 882ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 883ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 884d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 885d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 886ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 887f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 888ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 889ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 890b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 891b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 892b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 893b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 8940c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 8950c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 896b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 897b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 898eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 899eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 900eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 901eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 902eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 903eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 904341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 905341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 906341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 907fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 908341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 909341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 910341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 91168936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 91268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 91368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 91468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 91568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 916e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 91768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 91868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 91968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 920eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 921eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 922373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 9234dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 9240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 9250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 92682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 92782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 92882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 92970c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 93070c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 93182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 93282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 93382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 93482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 9350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 9360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 9370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 9380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 9390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 94082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 94119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 9421b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 9431b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 9441b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 9451b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 9461b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 9471b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 9481b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 9491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 9501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 9511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 9524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 9534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 9543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 9553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey map.put(toField, fromField + " AS " + toField); 9563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 9573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 9583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 9603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 9623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 964653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 9653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9661129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov @SuppressWarnings("all") 9673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 9683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 969a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 970a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 971a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 972a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 973a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 974a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 975a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 976a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 9773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 979653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 980653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 981b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 982653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 983653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 984653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 985653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 9863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 9883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 990e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 991e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 992e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 993e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 994653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 995e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 996e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 997e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 9983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 10013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 10023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 1003813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * 1004813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * @return true if update changed something 10053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1006813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1007f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 100814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 100914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1010653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1011653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 1012653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 1013653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 1014653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 1015653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1016653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 1017653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 1018653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 1019653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 1020653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 1021653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1022653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 1023653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 1024653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1025653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1026653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 10274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " =?", mSelectionArgs1); 1029653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1030653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1031f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1032653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 1033653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1034813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1035813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 10363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 103914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 104014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 104114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 10424da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=?", mSelectionArgs1); 10444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 10454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=?", mSelectionArgs1); 10463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 10475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 10483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 10503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 10534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov long mimeTypeId = getMimeTypeId(); 1054e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 1055e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 10564da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 10574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = db.query(DataDeleteQuery.TABLE, 10584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov DataDeleteQuery.CONCRETE_COLUMNS, 10594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Data.RAW_CONTACT_ID + "=?" + 10604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov " AND " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId, 10614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 10623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 1063e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 106414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 1065f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 1066e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 1067e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 1068e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 1069e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 10703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 10723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 10733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (primaryId != -1) { 10754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov setIsPrimary(rawContactId, primaryId, mimeTypeId); 10764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 1077e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1078e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1079e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 1080e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 1081e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 1082e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 1083e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1084e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 10853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 108725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 1088285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1089d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(db, rawContactId); 1090fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(db, rawContactId); 1091285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 10923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1093a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1094622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1095622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 1096813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * as baseline, but augmented with any updates. Returns null if there is 1097813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * no change. 1098622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1099622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 1100622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 1101813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov boolean changing = false; 1102622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 11034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 11044da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=?", 11054da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 1106622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 1107622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 1108622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 1109622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 1110813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov final String value = cursor.getString(i); 1111813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!changing && update.containsKey(key)) { 1112813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov Object newValue = update.get(key); 1113813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String newString = newValue == null ? null : newValue.toString(); 1114813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov changing |= !TextUtils.equals(newString, value); 1115813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1116813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov values.put(key, value); 1117622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1118622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1119622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 1120622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 1121622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1122813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!changing) { 1123813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 1124813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1125813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1126622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 1127622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 1128622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 11323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 11343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 11353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1139622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 11403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1141622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 11423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1143622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 11443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1148622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 114914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 115014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 115114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1152f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1153d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov Integer fullNameStyle = values.getAsInteger(StructuredName.FULL_NAME_STYLE); 1154d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name, 115551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov fullNameStyle != null 115651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov ? mNameSplitter.getAdjustedFullNameStyle(fullNameStyle) 115751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov : FullNameStyle.UNDEFINED); 115848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, values); 115925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1160813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 116114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 116214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 116314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 116414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1165813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1166f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1167622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1168622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1169cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1170622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1171813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1172813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1173813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1174813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1175622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 117614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1177f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1178f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 1179f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1180f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 1181d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov Integer fullNameStyle = values.getAsInteger(StructuredName.FULL_NAME_STYLE); 1182d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name, 118351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov fullNameStyle != null 118451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov ? mNameSplitter.getAdjustedFullNameStyle(fullNameStyle) 118551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov : FullNameStyle.UNDEFINED); 118648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, values); 118714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 118825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1189813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1190813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 119114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 119214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 119314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 119414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 119514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 119614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 119714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 119814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 119914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1200f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 120125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1202813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 120314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 12043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1207622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 12083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1209622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1210622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1211622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1212622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 12133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1214622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1215622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1216622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1217622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1218622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1219622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1220622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 122167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1222622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 122367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 122467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1225622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1226622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 12278c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1228622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1229622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 123067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 123167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 123267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 123367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 123467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 123567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 12368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1237622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 12384cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao // As the name could be changed, let's guess the name style again. 12394cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao name.fullNameStyle = FullNameStyle.UNDEFINED; 12404cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mSplitter.guessNameStyle(name); 12415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 12425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov final String joined = mSplitter.join(name, true); 1243622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 12445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 12455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov update.put(StructuredName.FULL_NAME_STYLE, name.fullNameStyle); 12465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, name.phoneticNameStyle); 12474cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } else if (touchedUnstruct && touchedStruct){ 1248d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov if (!update.containsKey(StructuredName.FULL_NAME_STYLE)) { 1249d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov update.put(StructuredName.FULL_NAME_STYLE, 1250d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mSplitter.guessFullNameStyle(unstruct)); 12514cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1252d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov if (!update.containsKey(StructuredName.PHONETIC_NAME_STYLE)) { 1253d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, 1254d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mSplitter.guessPhoneticNameStyle(unstruct)); 12554cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1256622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1257622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1258622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1259622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1260622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1261622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1262622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1263622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1264622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1265622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1266622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1267622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1268622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1269622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1270622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1271622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1272622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1273622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1274622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1275813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1276f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1277622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1278622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1279813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1280813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1281813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1282813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1283622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1284f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1285813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 1286622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1287622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1288622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1289622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1290622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1291622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1292622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1293622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1294622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1295622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1296622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1297622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1298622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1299622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1300622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1301622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1302622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1303622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 130467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 130567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 130667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 130767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1308622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1309622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1310622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1311622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1312622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1313622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 131467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 131567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 131667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1317622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1318622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1319622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 13203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 13253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 13273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 13283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 13303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 13313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 13323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 13333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1337622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1338622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1339622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1341622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1342813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1343f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1344622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1345622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1346813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1347813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1348813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1349622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1350813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return super.update(db, values, c, callerIsSyncAdapter); 1351622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1353622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1354622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1355622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1356622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1357622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1358622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1359622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1360622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 13613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1362622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1363622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1364622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1365622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1366622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 13713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 13733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 13743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1378a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1379a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1380a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1381a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1382a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 138325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1384a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1385a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 13863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 1389813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1390f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1391813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1392813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1393813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 139414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 139531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov boolean containsCompany = values.containsKey(Organization.COMPANY); 139631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov boolean containsTitle = values.containsKey(Organization.TITLE); 139731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsCompany || containsTitle) { 1398813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1399813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1400813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 140131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov String company; 140231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 140331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsCompany) { 140431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov company = values.getAsString(Organization.COMPANY); 140531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } else { 140631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 140731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov company = DatabaseUtils.stringForQuery(db, 140831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov "SELECT " + Organization.COMPANY + 140931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " FROM " + Tables.DATA + 141031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " WHERE " + Data._ID + "=?", mSelectionArgs1); 141131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 141231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 141331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov String title; 141431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsTitle) { 141531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov title = values.getAsString(Organization.TITLE); 141631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } else { 141731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 141831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov title = DatabaseUtils.stringForQuery(db, 141931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov "SELECT " + Organization.TITLE + 142031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " FROM " + Tables.DATA + 142131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " WHERE " + Data._ID + "=?", mSelectionArgs1); 142231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 142331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 142431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov deleteNameLookup(dataId); 142531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov insertNameLookupForOrganization(rawContactId, dataId, company, title); 142631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 142731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 142831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 1429813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 143014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 143114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 143214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 143314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1434a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 143514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 143614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 143714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 143825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1439a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 144014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 144114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 144214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 144314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 14443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 14453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 14463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 14473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 14483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 14493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 14503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1454e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1455e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1456e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1457e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1458e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1459e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1460e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 14615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1462813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String email = values.getAsString(Email.DATA); 146314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 146514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1467813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String address = insertNameLookupForEmail(rawContactId, dataId, email); 1468813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (address != null) { 1469813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1470813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 147114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 147214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 147314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 147414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1475813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1476f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1477813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1478813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1479813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 148014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1481b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (values.containsKey(Email.DATA)) { 1482813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1483813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1484813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1485b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String address = values.getAsString(Email.DATA); 1486b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov deleteNameLookup(dataId); 1487b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 1488b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1489813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1490b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov } 1491813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1492813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 149314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 149414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 149514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 149614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 149714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 149814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 149914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 150014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 150114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1502f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 150325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1504813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 150514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1506e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1507e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1508e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1509e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1510e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1511e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1512e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1513e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1514e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1515e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1516e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1517e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1518e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1519e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 152014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 152114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 152214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 152314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 152414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 152514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 152614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 152714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 152814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 152914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 153014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 153114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1532813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!TextUtils.isEmpty(nickname)) { 1533813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1534813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1535813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1536813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 153714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 153814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 153914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 154014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1541813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1542f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 154314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 154414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 154514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1546813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1547813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1548813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 154914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1550b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (values.containsKey(Nickname.NAME)) { 1551b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 1552b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov deleteNameLookup(dataId); 1553b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1554b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1555813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1556b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov } 1557813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1558813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 155914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 156014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 156114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 156214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 156314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 156414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 156514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 156614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 156714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1568f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 156925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1570813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 157114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 157214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 157314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 157414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 15753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 15763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 15783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 15793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 15825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 15830b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 15840b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 15850b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 1586813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number); 1587813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 15880b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1589653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 15900b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1591285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 159225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1593813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (normalizedNumber != null) { 1594813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1595813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 15960b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 15970b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 15980b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1599653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1600653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1601653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1602653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1603813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1604f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1605813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String number = null; 1606813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String normalizedNumber = null; 16070b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 1608813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov number = values.getAsString(Phone.NUMBER); 1609813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov normalizedNumber = computeNormalizedNumber(number); 1610813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1611813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1612653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1613813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1614813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1615813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1616653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1617813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 1618813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1619813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 16200b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1621285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 162225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1623813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 16240b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1625813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 162614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 162714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 162814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 162914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 163014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 163114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 163214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 163314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 163414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 163514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1636285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 163725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1638813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 163914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1640653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1641653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1642813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov private String computeNormalizedNumber(String number) { 1643e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1644e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1645e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1646e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1647653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1648653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1649e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1650653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1651653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1652e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1653653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 16545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1655653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1656e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 165736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.MIN_MATCH, 165836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov PhoneNumberUtils.toCallerIDMinMatch(number)); 165936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov 1660653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1661653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 16624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 16634da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=?", mSelectionArgs1); 1664e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 16653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 16673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 16683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 16693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 16703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 16713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 16723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 16733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 16743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 16753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 16763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 16773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 16783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 16793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1683653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1684653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1685653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1686653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1687653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1688653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1689653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1690653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1691653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 16920be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 16930be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 16940be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1695653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1696653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1697653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1698813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1699f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 170014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1701653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1702813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1703813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1704813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 17050be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 1706813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 17070be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 17080be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 17090be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 17100be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 17110be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 17120be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 17130be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 17140be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 17150be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 17160be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 17170be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1718b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 17190be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1720b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 17210be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1722653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1723653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1724653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1725653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1726653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1727653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1728653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1729653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1730653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1731653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1732653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1733653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1734653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1735653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1736653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1737653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1738653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1739653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1740653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1741653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1742653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1743653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1744653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1745653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1746ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId, 1747ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.get(rawContactId)); 1748653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1749653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1750653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1751653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1752653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1753653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1754a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1755a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1756a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1757a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1758a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1759a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1760a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1761a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1762a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1763285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1764285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1765285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1766a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1767a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1768a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1769a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1770813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1771f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1772a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1773813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1774813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1775813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1776813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1777a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1778813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 1779a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1780a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1781a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1782a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1783a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1784a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1785a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1786a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1787a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1788a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1789a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1790ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov /** 1791ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 1792ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1793ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1794ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov public class GroupIdCacheEntry { 1795ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1796ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 1797ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1798ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1799ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1800a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 18013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 1802b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 180331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 18044097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1805f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1806315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1807622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1808622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1809ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1810ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1811ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // is a list of groups with this group id. 1812ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1813ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 1814622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1815f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1816a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1817d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1818a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 181920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 18201129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private CharArrayBuffer mCharArrayBuffer = new CharArrayBuffer(128); 18215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private NameSplitter.Name mName = new NameSplitter.Name(); 182273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 182320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 182409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 182509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 1826ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 182773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1828ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<Long, Account> mInsertedRawContacts = Maps.newHashMap(); 1829b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1830a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private HashSet<Long> mDirtyRawContacts = Sets.newHashSet(); 1831b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1832de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 18331a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 18341a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 183581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 183681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 18374cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 1838d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 183973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 18404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 18414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1842de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1843ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1844ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1845ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1846ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1847ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1848ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1849ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 185035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1851ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 1852de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1853b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1854a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1855b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1856d076a108d58b30591f197e1b90fa8de60999c499Dmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper); 18570e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1858a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1859b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 1860653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 186151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov initForDefaultLocale(); 1862d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1863b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mSetPrimaryStatement = mDb.compileStatement( 1864653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1865653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1866653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1867653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1868653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1869b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mSetSuperPrimaryStatement = mDb.compileStatement( 1870653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1871653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1872653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1873653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1874653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1875653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1876653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1877653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1878653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1879653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1880653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1881b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mRawContactDisplayNameUpdate = mDb.compileStatement( 188225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 18835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov " SET " + 18845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE + "=?," + 18855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY + "=?," + 18865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," + 18875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME + "=?," + 18885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE + "=?," + 18895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY + "=?," + 18905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE + "=?" + 189125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 18923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1893b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mLastStatusUpdate = mDb.compileStatement( 1894a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.CONTACTS + 1895a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1896a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1897a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1898a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1899a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1900a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1901a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1902a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1903a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1904a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 19050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 19060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1907a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " LIMIT 1)" + 1908a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1909e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1910b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mNameLookupInsert = mDb.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1911f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1912f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1913f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1914b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mNameLookupDelete = mDb.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1915f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1916f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1917b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateInsert = mDb.compileStatement( 1918a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1919a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 19200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 19210a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 19220a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 19230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 19240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 1925a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1926b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateReplace = mDb.compileStatement( 1927a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1928a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 19290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 19300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 19310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 19320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 19330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 19340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1935a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1936b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateAutoTimestamp = mDb.compileStatement( 1937a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 19380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 19390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 1940a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 19410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 19420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 1943b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusAttributionUpdate = mDb.compileStatement( 19440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 19450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 19460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 19470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 19480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1949a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1950b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateDelete = mDb.compileStatement( 1951a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1952a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1953a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1954f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // When setting NAME_VERIFIED to 1 on a raw contact, reset it to 0 1955f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // on all other raw contacts in the same aggregate 1956b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mResetNameVerifiedForOtherRawContacts = mDb.compileStatement( 1957f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 1958f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " SET " + RawContacts.NAME_VERIFIED + "=0" + 1959f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=(" + 1960f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1961f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1962f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?)" + 1963f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " AND " + RawContacts._ID + "!=?"); 1964f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 19653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 19663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1967e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 19683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 19693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 197067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 197167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 19723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 19733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 197414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 19753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 19763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 1977622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1978622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey new StructuredPostalRowHandler(mPostalSplitter)); 1979a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1980a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 19813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1982f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1983f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 19841129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdStructuredName = mDbHelper.getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE); 19851129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdOrganization = mDbHelper.getMimeTypeId(Organization.CONTENT_ITEM_TYPE); 19861129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdNickname = mDbHelper.getMimeTypeId(Nickname.CONTENT_ITEM_TYPE); 19871129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdPhone = mDbHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 198804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov 1989bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov verifyAccounts(); 1990bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov verifyLocale(); 1991bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 199265ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 199365ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov importLegacyContactsAsync(); 199465ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov } 199565ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 1996b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return (mDb != null); 19974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 19984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 199951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 200051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 200151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 200204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 20034cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 200404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov mNameSplitter = mDbHelper.createNameSplitter(); 20054cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 20064cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 200751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mCommonNicknameCache = new CommonNicknameCache(mDbHelper.getReadableDatabase()); 2008cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 20094cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 20104cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 20114cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao @Override 201251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov public void onConfigurationChanged(Configuration newConfig) { 201351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov initForDefaultLocale(); 201451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov verifyLocale(); 20154cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 201651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2017c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 2018c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 2019c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 2020c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 2021c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 202251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 202351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 202451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 202551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 202651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 202751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 202851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 202951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void verifyLocale() { 2030f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 2031f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 2032f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 2033f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 2034f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 2035f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 203651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 203751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 203851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (providerLocale == null) { 203951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov // The provider has just been created for the first time. There are no 204051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov // contacts in the database, so we can safely set locale on the UI thread. 204151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mDbHelper.setLocale(ContactsProvider2.this, mCurrentLocale); 204251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 204351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 204451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 204551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 204651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 204751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 204851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 204951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 205051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 205151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 205251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 205351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 205451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov AsyncTask<Integer, Void, Void> task = new AsyncTask<Integer, Void, Void>() { 205551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 205651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int savedProviderStatus; 205751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 205851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov @Override 205951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected Void doInBackground(Integer... params) { 206051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov savedProviderStatus = params[0]; 206151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mDbHelper.setLocale(ContactsProvider2.this, currentLocale); 206251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return null; 206351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 206451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 206551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov @Override 206651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void onPostExecute(Void result) { 206751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).commit(); 206851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(savedProviderStatus); 2069f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 2070f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // Recursive invocation, needed to cover the case where locale 2071f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // changes once and then changes again before the db upgrade is completed. 2072f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov verifyLocale(); 207351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 207451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov }; 207551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 207651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov task.execute(providerStatus); 207751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 207851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 207931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 2080de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 2081b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 2082b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 208331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 208431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 2085013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 2086013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 2087013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 2088013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 20895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 20905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 20915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 20925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 20935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 20943d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 2095b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 2096b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 20973d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 20983d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2099568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 2100568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 2101568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2102568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2103568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 2104568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 2105568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 2106568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 2107568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 2108bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 2109bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 2110bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (mAccessLatch == null) { 2111bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 2112bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2113568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2114568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 2115568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2116568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 2117bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 2118bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importLegacyContacts(importer)) { 2119bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov onLegacyContactImportSuccess(); 2120bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2121bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov onLegacyContactImportFailure(); 2122568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2123568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2124568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 2125568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2126568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 2127568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2128568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2129bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 2130bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 2131bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 2132bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 2133bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 2134bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 2135bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 2136bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2137b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 2138b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDbHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 2139b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 2140bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 2141bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch.countDown(); 2142bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch = null; 2143bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 2144bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2145bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2146bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 2147bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 2148bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 2149bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 2150bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 2151bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 2152bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 2153bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2154bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 2155bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 2156bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 2157bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 2158bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 2159bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 2160bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 2161bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 2162bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 2163bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2164bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 2165bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2166bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 2167bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 21683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 21693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 21703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 2171568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 21720e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 21733d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 21743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 2175bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 2176bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2177bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 2178bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 2179bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 2180bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 21813d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 21823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 21833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 2184bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 2185bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 21863d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 21873d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2188a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 2189a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 2190a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 2191a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 2192b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 2193a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 2194a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2195568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 2196568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 2197568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 2198568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 2199568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 2200568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 2201568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 2202568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 2203ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 2204ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 2205ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 2206ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 2207ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 2208ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 2209ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 2210ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 221181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 2212ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2213ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2214568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2215568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2216568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2217568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2218568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 2219568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2220568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 2221568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2222568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2223568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2224568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 2225bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (mAccessLatch != null) { 2226bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 2227bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 2228bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 2229bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 2230bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (match == PROVIDER_STATUS && isLegacyContactImportNeeded()) { 2231bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 2232bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 2233bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov importLegacyContactsAsync(); 2234bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 2235bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2236bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 2237bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2238bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2239bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2240568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2241568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 2242568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2243568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2244568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2245568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 2246568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2247568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 2248568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2249568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2250568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2251568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2252568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 2253568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2254568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 2255568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2256568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 22574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2258285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 2259bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2260b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 2261b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2262285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 22631ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 2264b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2265b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2266b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2267b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 2268285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 2269b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 2270df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 2271a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.clear(); 2272285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2273285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2274285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2275285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 22761129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 2277bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2278b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2279b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2280285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 2281b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 22821ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 22831a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 22841a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 2285b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 22861a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 2287b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2288b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2289b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2290bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2291b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2292b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 22931129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 229408e42c9c153a60bf2e7c71dd40bf84bb5fc93555Dmitri Plotnikov for (long rawContactId : mInsertedRawContacts.keySet()) { 2295d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(mDb, rawContactId); 2296d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mContactAggregator.onRawContactInsert(mDb, rawContactId); 2297285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2298b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2299a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov if (!mDirtyRawContacts.isEmpty()) { 2300a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2301a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2302a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mDirtyRawContacts); 2303a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2304a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2305a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2306a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2307b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 2308a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2309a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2310a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mUpdatedRawContacts); 2311a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2312a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2313b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2314b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2315b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 2316b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 23179d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana if (mDbHelper.getSyncState().update(mDb, id, entry.getValue()) <= 0) { 23189d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 23199d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 23209d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 2321b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2322b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2323b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2324b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2325b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2326a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2327a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2328a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2329a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2330a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private void appendIds(StringBuilder sb, HashSet<Long> ids) { 2331b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2332a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2333b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2334a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2335a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2336285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2337285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2338285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2339cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 234081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 234181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 234281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 234381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 234481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 234581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 234681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2347cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2348568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 234951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 235051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mProviderStatus = status; 235151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.ProviderStatus.CONTENT_URI, 235251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov null, false); 235351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 235451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2355285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 2356ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return mInsertedRawContacts.containsKey(rawContactId); 2357285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2358285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 23593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 23603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 23613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 23623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 23633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 23643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 23663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 23684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2369de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2370bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 23711129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2372b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2373f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2374f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2375f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2376f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2377a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2378a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 237935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2380a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 238135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2382b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 238335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 238435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2385d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2386d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 23876bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 23886bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 23896bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 23905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2391f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertRawContact(uri, values); 2392f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2393a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2394a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2395a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 23965ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 23975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2398f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2399f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2400a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2401a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2402a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2403a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2404f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2405f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2406a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2407a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2408a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2409ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2410f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2411f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2412ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2413ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2414ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2415eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 24165aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 241743880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2418eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2419eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2420eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 242182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 242282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 24231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 24241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2426a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 242781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2428f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2429a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2430a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 24327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 24337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2435de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2436a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2437a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2438a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2439e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2440e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2441e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2442e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2443e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2444e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2445e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2446e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2447e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2448e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2449e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2450e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2451e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 24527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2453e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2454f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2455f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2456e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2457f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2458f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2459f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2460e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2461e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2462e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2463e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2464e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 2465fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2466fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 2467e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2468e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2469e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2470e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2471e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2472e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2473e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2474e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2475e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2476e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2477e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2478e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 2479fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2480fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 2481e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2482e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2483e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2484f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2485f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2486e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2487f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2488f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2489e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2490e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2491f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2492f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2493e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2494f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2495f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2496f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2497f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2498035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2499f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2500e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 25017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2504d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 25056bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 25066bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 25076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 25086bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2509d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2510de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 25116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 25126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 25136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2514a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2515a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2516f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2517f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2518a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2519a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2520f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertRawContact(Uri uri, ContentValues values) { 2521f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2522f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2523f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2524f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2525e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 25267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25273d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 25283d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2529f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 25303d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 25313d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2532f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 2533f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 2534f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 2535f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 2536f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2537f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId, aggregationMode); 2538285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2539285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2540e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mInsertedRawContacts.put(rawContactId, account); 2541f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2542023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2543a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2544a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2545a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2546a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2547a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2548a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2549a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2550a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2551f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2552a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2553de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2554de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 255567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2556de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 255720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2558de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2559de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2560de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2561b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2562de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2563de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2564508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2565de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2566de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2567de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2568de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2569de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 25704097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2571b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2572de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2573a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2574a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2575a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2576f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2577de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2578a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2579b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2580a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 25814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 25824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 25838e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 25848e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 25858e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 25868e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 25878e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2588b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2589f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 25908e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 25918e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 25928e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 25938e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 2594f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode); 2595f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 25968e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 25978e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 25988e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2599b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2600f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 26018e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 26028e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 26038e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2604f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 26058e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2606f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2607c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 2608b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 26098e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2610f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 26118e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2612f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2613f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2614f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2615a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 26165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 26179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 26189261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 26195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 26209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 26219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 26229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 26239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 26249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 2625ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId, 2626ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Account account) { 2627ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2628ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (account == null) { 26294da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 2630ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 26314da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov RawContacts._ID + "=?", mSelectionArgs1, null, null, null); 2632ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov try { 2633ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2634ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = c.getString(RawContactsQuery.ACCOUNT_NAME); 2635ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = c.getString(RawContactsQuery.ACCOUNT_TYPE); 2636ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 2637ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov account = new Account(accountName, accountType); 2638ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 26399261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2640ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } finally { 2641ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov c.close(); 26429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 26439261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2644ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 26459261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 26469261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 2647ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov + "has a sourceid the the contact must be associated with " 26489261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 26499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 26509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2651ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ArrayList<GroupIdCacheEntry> entries = mGroupIdCache.get(sourceId); 2652ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entries == null) { 2653ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries = new ArrayList<GroupIdCacheEntry>(1); 2654ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.put(sourceId, entries); 2655ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2656ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2657ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int count = entries.size(); 2658ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov for (int i = 0; i < count; i++) { 2659ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = entries.get(i); 2660ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entry.accountName.equals(account.name) && entry.accountType.equals(account.type)) { 2661ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 2662ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2663ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2664ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2665ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = new GroupIdCacheEntry(); 2666ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountName = account.name; 2667ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountType = account.type; 2668ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.sourceId = sourceId; 2669ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries.add(0, entry); 2670ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 26719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 26725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 2673ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 26749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2675df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 26769261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 2677ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2678ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = c.getLong(0); 26799261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 26809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2681df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2682df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 26839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 26849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 26859261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 26869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 26879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 26889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2689ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = groupId; 26909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 26919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 26929261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 26939261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2694ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2695ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 26969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 26979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2698d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private interface DisplayNameQuery { 26991129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov public static final String RAW_SQL = 27001129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov "SELECT " 27011129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + DataColumns.MIMETYPE_ID + "," 27021129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.IS_PRIMARY + "," 27031129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.DATA1 + "," 27045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA2 + "," 27055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA3 + "," 27065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA4 + "," 27075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA5 + "," 27085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA6 + "," 27095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA7 + "," 27105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA8 + "," 27115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA9 + "," 27125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA10 + "," 27135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA11 + 27141129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " FROM " + Tables.DATA + 27151129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " WHERE " + Data.RAW_CONTACT_ID + "=?" + 27161129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " AND (" + Data.DATA1 + " NOT NULL OR " + 27171129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Organization.TITLE + " NOT NULL)"; 2718d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2719d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int MIMETYPE = 0; 2720d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int IS_PRIMARY = 1; 27215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int DATA1 = 2; 27225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int GIVEN_NAME = 3; // data2 27235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FAMILY_NAME = 4; // data3 27245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PREFIX = 5; // data4 27255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int TITLE = 5; // data4 27265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int MIDDLE_NAME = 6; // data5 27275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int SUFFIX = 7; // data6 27285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_GIVEN_NAME = 8; // data7 27295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_MIDDLE_NAME = 9; // data8 27305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME = 9; // data8 27315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_FAMILY_NAME = 10; // data9 27325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FULL_NAME_STYLE = 11; // data10 27335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME_STYLE = 11; // data10 27345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_NAME_STYLE = 12; // data11 2735d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2736d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2737d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov /** 2738d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * Updates a raw contact display name based on data rows, e.g. structured name, 2739d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * organization, email etc. 2740d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov */ 2741ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 2742bca1c8b44f99528fc123d5547723e44771e8e934Mike Lockwood int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 27435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name bestName = null; 27445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestDisplayName = null; 27455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestPhoneticName = null; 27465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 2747d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 27481129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 27491129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Cursor c = db.rawQuery(DisplayNameQuery.RAW_SQL, mSelectionArgs1); 2750d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov try { 2751d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov while (c.moveToNext()) { 27521129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov int mimeType = c.getInt(DisplayNameQuery.MIMETYPE); 27535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int source = getDisplayNameSource(mimeType); 27545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source < bestDisplayNameSource || source == DisplayNameSources.UNDEFINED) { 27555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 27565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 27571129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 27585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source == bestDisplayNameSource && c.getInt(DisplayNameQuery.IS_PRIMARY) == 0) { 27595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 2760d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 27611129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 27625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mimeType == mMimeTypeIdStructuredName) { 27635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name name; 27645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestName != null) { 27655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = new NameSplitter.Name(); 27665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 27675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = mName; 27685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.clear(); 27695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 27705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.prefix = c.getString(DisplayNameQuery.PREFIX); 27715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.givenNames = c.getString(DisplayNameQuery.GIVEN_NAME); 27725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.middleName = c.getString(DisplayNameQuery.MIDDLE_NAME); 27735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.familyName = c.getString(DisplayNameQuery.FAMILY_NAME); 27745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.suffix = c.getString(DisplayNameQuery.SUFFIX); 27755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.fullNameStyle = c.isNull(DisplayNameQuery.FULL_NAME_STYLE) 27765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? FullNameStyle.UNDEFINED 27775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.FULL_NAME_STYLE); 27785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticFamilyName = c.getString(DisplayNameQuery.PHONETIC_FAMILY_NAME); 27795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticMiddleName = c.getString(DisplayNameQuery.PHONETIC_MIDDLE_NAME); 27805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticGivenName = c.getString(DisplayNameQuery.PHONETIC_GIVEN_NAME); 27815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticNameStyle = c.isNull(DisplayNameQuery.PHONETIC_NAME_STYLE) 27825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 27835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.PHONETIC_NAME_STYLE); 27845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (!name.isEmpty()) { 27855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 27865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName = name; 27875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 27885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else if (mimeType == mMimeTypeIdOrganization) { 27895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 27905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 27915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 2792d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov bestDisplayNameSource = source; 27931129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 27941129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 27955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = c.getString(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME); 27965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = 27975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.isNull(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE) 27985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 27995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE); 28005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 28015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.TITLE, mCharArrayBuffer); 28025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 28031129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayNameSource = source; 28041129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 28051129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 28065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 28075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 28081129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 2809d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 28105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 28115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Display name is at DATA1 in all other types. 28125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // This is ensured in the constructor. 28135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 28155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 28165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 28175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 28185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 28195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 28205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 28215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 28225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 2823d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2824d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2825d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2826d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } finally { 2827d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov c.close(); 2828d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2829d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 28305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary; 28315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNameAlternative; 28325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyPrimary = null; 28335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyAlternative = null; 28345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int displayNameStyle = FullNameStyle.UNDEFINED; 28355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestDisplayNameSource == DisplayNameSources.STRUCTURED_NAME) { 28375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = bestName.fullNameStyle; 28385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.CJK 28395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.UNDEFINED) { 28405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 28415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName.fullNameStyle = displayNameStyle; 28425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = mNameSplitter.join(bestName, true); 28455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative = mNameSplitter.join(bestName, false); 28465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = mNameSplitter.joinPhoneticName(bestName); 28485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = bestName.phoneticNameStyle; 28495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 28505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = displayNameAlternative = bestDisplayName; 28515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticName != null) { 28545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = bestPhoneticName; 28555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticNameStyle == PhoneticNameStyle.UNDEFINED) { 28565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = mNameSplitter.guessPhoneticNameStyle(bestPhoneticName); 28575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 28595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED) { 28605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.guessFullNameStyle(bestDisplayName); 28615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED 28625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.CJK) { 28635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedNameStyleBasedOnPhoneticNameStyle( 28645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle, bestPhoneticNameStyle); 28655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 28675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.CHINESE) { 28695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = 2870cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().getSortKey( 2871cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao displayNamePrimary, FullNameStyle.CHINESE); 28725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (sortKeyPrimary == null) { 28765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = displayNamePrimary; 28775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyAlternative = displayNameAlternative; 28785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov setDisplayName(rawContactId, bestDisplayNameSource, displayNamePrimary, 28815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative, bestPhoneticName, bestPhoneticNameStyle, 28825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary, sortKeyAlternative); 2883d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2884d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 28851129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private int getDisplayNameSource(int mimeTypeId) { 28861129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (mimeTypeId == mMimeTypeIdStructuredName) { 28871129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.STRUCTURED_NAME; 28881129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdEmail) { 28891129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.EMAIL; 28901129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdPhone) { 28911129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.PHONE; 28921129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdOrganization) { 28931129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.ORGANIZATION; 28941129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdNickname) { 28951129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.NICKNAME; 28961129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else { 28971129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.UNDEFINED; 28981129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 28991129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 29001129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 29019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 290220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 290320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2904f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 290520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 290620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2907de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2908de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 290914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2910de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2911de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 291214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 291314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2914a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2915a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2916f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 291788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 291888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 291920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 292020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2921de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 292220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 292320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 292420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 292520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 292620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 292788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 292888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 292988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 293020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2931f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 293288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 293388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 29344da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 29354da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=?", 29364da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 2937f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 293820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 293920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 294020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 294120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 294220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 294314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 294420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 294520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 294620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 294720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 294820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 294920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 295020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 295120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 295220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 29537a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 295420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 295520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 295620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2957a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2958813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return rowHandler.delete(mDb, c); 295920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 296020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 296120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 296220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 296320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 296420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2965ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2966ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2967f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2968f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2969f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2970f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2971e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 2972ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2973ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 2974f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 297567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 2976f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 297767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 2978f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 2979ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2980f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2981f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 298273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 298373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2984f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 2985ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2986f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 29871a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2988ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2989ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2990ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2991ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2992ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 29935aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2994e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 29955aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 29961a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 29971a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2998e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 29991a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 3000e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 3001e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3002e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3003ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 300482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 30051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 300682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 300782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 30080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 30094dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 30104dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 30110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 301282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 30134dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 30144dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 30154dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 30164dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 30171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 30181f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3019dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 3020dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 302182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 3022f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 30232526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 3024dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 3025dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 3026dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 30272526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 30282526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 30291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 3030dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 3031dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 30320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 30330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 30340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 30350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3036dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 3037dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 3038dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 30392526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov String mimeTypeIdIm = String.valueOf(mMimeTypeIdIm); 3040dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 30412526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov String mimeTypeIdEmail = String.valueOf(mMimeTypeIdEmail); 3042f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3043f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 3044f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 3045f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 3046f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3047f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 3048f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 30492526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 30502526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 30512526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 30522526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 30532526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 30542526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 30552526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 30562526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 3057dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 30582526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 30592526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3060dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 30612526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 30622526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 3063dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 30642526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 30652526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 30662526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 30672526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 30682526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 30692526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 3070dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 30712526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 30722526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3073dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 3074dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 30751f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 307682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 30772526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 30782526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 3079dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 308070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 3081f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 308270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 30831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 30841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 3085de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 30862526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 3087c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 30881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 308967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 30905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 3091e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 30921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 30931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 30941f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 30951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 30961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 309731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 309831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 309931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 31001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31011f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 310282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 3103a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 3104a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 3105a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 3106a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 3107a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3108a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3109a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 311082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 3111a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 3112a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 311382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 311482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 311582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 311682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 311782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 3118a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 311982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 312082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 31211f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3122a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 3123a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 3124a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3125e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 31260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 312782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 312882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 31290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 31300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 31310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 31320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 31330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 31340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 31350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 31360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 31370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 31380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 31390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 31400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3141a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 3142a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 3143a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 314482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 314582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 3146a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 3147a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 31485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 3, status); 31495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 4, resPackage); 31505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 5, iconResource); 31515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 6, labelResource); 3152a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 3153a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 3154a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3155a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 3156a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 31575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 2, status); 31585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 3, resPackage); 31595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 4, iconResource); 31605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 5, labelResource); 3161a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 3162a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 3163a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 31640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 3165a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 31665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 2, status); 3167a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 31685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 4, status); 3169a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 31700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 31715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusAttributionUpdate, 1, resPackage); 31725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 2, iconResource); 31735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 3, labelResource); 31740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 31750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 3176a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3177e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3178e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3179bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3180a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 3181a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 3182a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 3183a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 3184a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3185a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3186a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 31871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 31894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3190de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 3191bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3192b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 3193b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3194b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3195f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3196f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 3197508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 3198508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 319935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3200b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 320135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3202b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 3203b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3204b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3205b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3206b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 3207b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3208cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 3209cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 3210cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 3211cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3212cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3213d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3214d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3215cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 32166bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 32176bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 32189fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 32192e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 32202e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 32212e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3222fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3223fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 32242e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 32252e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 32262e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 32272e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 32282e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 32292e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 32309fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 32319fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 32329fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann long contactId = ContentUris.parseId(uri); 32339fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 32349fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 32359fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 32369fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 32379fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 32389fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 32399fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 32409fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 32419fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 32429fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 32439fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 32449fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 324560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 32469fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 32479fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 32489fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann Cursor c = query(db, lookupQb, null, selection, args, null, null, null); 32499fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 32509fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 32519fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 32529fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return deleteContact(contactId); 32539fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 32549fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 32559fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 32569fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 32579fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 32589fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 32599fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 32609fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 32619fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 32629fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 32632971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 32642971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 3265fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, 3266fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 3267e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 32682971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 32692971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 32702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 3271fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 3272fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 3273fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 32742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 32752971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 32762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 32772971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 32782971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 32792971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 32802971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 32815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 32822971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 3283fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return deleteRawContact(rawContactId, mDbHelper.getContactId(rawContactId), 3284fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 3285508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3286508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 328720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3288f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 3289944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 3290f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 329120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 329220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 329348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 329448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 329548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 329648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3297508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3298f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 32994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 33004da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 3301ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3302ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3303ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3304f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 33055aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 33062971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 33072971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 33082971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 33092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 33102971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 3311e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 33122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 33132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 33145aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 33152971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 33162971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 33172971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 33182971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 331981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3320f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 332181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 33222971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3323508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3324508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3325eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 332643880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3327e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3328eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3329eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 333082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 33310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 33321f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 33331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 333481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 333581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 33363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 333781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3338508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 33394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 33404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 33411c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3342ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3343b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 334494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 3345de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 334694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 334794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 334894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 334994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3350f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 3351de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 335294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 335394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 335494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3355f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 3356de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 335794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 335894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 33591a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 336094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 336194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 336294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 33635aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 3364e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 33651a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3366e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3367e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3368e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3369cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 337096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 3371cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 337296b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 337396b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 3374cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3375cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3376cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3377cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 3378cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3379cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3380cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3381cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3382cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3383cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3384cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3385cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3386fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 33873389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3388f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 338914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 3390fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov int count = mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 3391fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForContact(mDb, contactId); 3392fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 339333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 3394b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 3395cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 339633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 339733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 339833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 33990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 34009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 34019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 34029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 34039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 34049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 34059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 34069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 34079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 34080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 34090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3410cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 341181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 341281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3413cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3414cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3415cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3416cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3417cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3418cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3419cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 3420cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3421cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 34224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3423de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3424de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3425bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3426b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3427b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3428b5a4add17815167d20a90645779df34cdf45280dFred Quintana 342935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 343000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 343100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3432b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3433b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 34341129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 3435b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 3436b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3437b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3438b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3439f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3440f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 344100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 344235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3443b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3444b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3445b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3446b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3447b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3448b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3449b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3450b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3451b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3452b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3453b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 345435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3455d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 34568c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 345700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 345800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 345900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3460d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 34618c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 3462c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3463c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3464c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 34652e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 34662e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 34672e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 34682e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 34692e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3470fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3471fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 34722e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34732e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 34742e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 34758c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 34762e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 34772e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34782e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 34797d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 34807d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 34817d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 34827d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 34837d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 34847d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 34857d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 34867d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 34877d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 34887d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 348920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3490944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3491f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 349281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3493f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 349481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 349520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 349620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3497c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 349848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 349948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 350048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 350148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3502f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 350381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3504f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 350581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 350600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 350700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 35087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 35095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 35105ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 35114529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 35127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 35137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 35147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 35155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 351633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 35174529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 35184da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 35194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 35204529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 35214529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 35224da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 35234da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1); 35244529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 35257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 35267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 35277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3528ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 35295aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3530f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 353181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3532f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 353381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3534ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3535ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3536ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3537ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3538ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 35394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 35404da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 354173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 35425aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 35435aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 354481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3545f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 354681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3547ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3548ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3549ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3550127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 3551de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 3552b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3553b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3554b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3555eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3556e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3557e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 355843880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3559eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3560eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3561eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 35629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 35639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 35649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 35659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 35669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 356781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 356881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 3569f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 357081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 357100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 357200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 357300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 35744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35769705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 35779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 35789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 35799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 35809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 35819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 35829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 35839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 35849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 35859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 35869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 35879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 35889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 35899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 35909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 35919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 35929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 35939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 35949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 35959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 35969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 35979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 35989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 35999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 36009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 36019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 36029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 36039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 36049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 36059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 36069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 36079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 36089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 36099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 36119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 36129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 36139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 36149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 36159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 36169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 36179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 36189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 36199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 36209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 36219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 36229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 36239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 36249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 36269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 36279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 36289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 36299705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 36309705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 36319705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36329705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 36335aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 3634f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 363573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3636ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3637ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 363873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 3639f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 364073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 364173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 364273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 364373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 364473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 364573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 364673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 364773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3648ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 36491a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 36501a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 365194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 36526ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 36531129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 36546ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 3655e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 36566ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 36576ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 36586ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 36596ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 36606ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 36616ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 36626ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 36636ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 36646ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 3665ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 36666ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 36676ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 36686ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 36696ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 36706ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 36716ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 36726ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 36736ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 367494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 367594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 367694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 3677b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 3678b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 3679e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 36801a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 36811a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3682e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3683e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3684e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3685e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 36864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 36874529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 36884529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 36894529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 36904529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 369173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 36924529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3693b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 369451bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 36954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 36964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 36974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 36984529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 36994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 37004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 37014529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 37024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 37034529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 37044529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 37054529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 37064529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 37074529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 37084529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 37094529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 371096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 371196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 371219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 371319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 371419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 3715ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 3716ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 371719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 371819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 371996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1, null, null, null); 372019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 372119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 372219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 3723ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 3724ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 372519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 372619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 372719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 372819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 372919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 373019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 373119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 3732f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 373396b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker int count = mDb.update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 37345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3735f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 3736f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 3737f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 3738f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 3739f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 3740f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 3741f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode); 3742f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 3743f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 3744433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 37454529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3746433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3747285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 37482b7a632bba423357ae5641f94da6a2f71afc523bDmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(mDb, rawContactId); 3749285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 3750f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 3751f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 3752f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 3753f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 3754f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 3755f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(1, rawContactId); 3756f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(2, rawContactId); 3757f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.execute(); 3758f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 3759f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(mDb, rawContactId); 3760f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 376119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 376219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 3763ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.put(rawContactId, new Account(accountName, accountType)); 376419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 37655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 376733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 376833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3769321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3770f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 377120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 377220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 377320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 37745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 377520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 377620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 377720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 377820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 377920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3780b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 378120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 378220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 378370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 378470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 378520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 378620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 378720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 378870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 378920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 379070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 379120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 379270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 379320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 379470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 379520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 379620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3797653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 379820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3799653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3800653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 380114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 3802653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 3803653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 3804f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 380520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3806653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 3807653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 380820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 380920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3810653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 381120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 381220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3813f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 3814653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 3815653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 3816321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3817653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 381814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 3819a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3820813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (rowHandler.update(mDb, values, c, callerIsSyncAdapter)) { 3821813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 1; 3822813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } else { 3823813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 0; 3824a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 3825321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3826321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 38278c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 38288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 38298c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 3830b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 38318c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 38328c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 38338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 38348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 38358c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 38368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 38378c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 38388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 38398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 38408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 38418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 38428c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 38438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 38448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 38458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 38468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 3847d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 38488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3849b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3850d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3851b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 3852d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3853b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 3854d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3855b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3856d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3857b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3858d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 3859d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3860d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 38618c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 3862d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 3863d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3864d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 38658c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 3866c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 38678c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3868c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 3869c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 38704da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 38714da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?", mSelectionArgs1); 38728c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 38738c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 38748c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 38758c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3876b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 38778c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3878b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 38798c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3880b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 38818c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3882b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 38838c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3884b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 38858c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 38868c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 38879b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori int rslt = mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 38886e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 38899b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 38909b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 38919b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 38929b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 38939b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 38949b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 3895f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3896d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3897127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 3898127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 38990c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 39000c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 390180c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 39020c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 39030c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 39040c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 39050c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 39060c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 39070c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 39080c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 3909b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3910127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 39110c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 39124da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 39134da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 39140c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 39154da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 39164da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 39170c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 39186bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 39196bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 39200c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 39210c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 39220c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 39230c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 3924127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 3925127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 39263389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3927f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1, RawContacts.AGGREGATION_MODE_DEFAULT); 3928f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2, RawContacts.AGGREGATION_MODE_DEFAULT); 3929dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 3930b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 39310c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 39320c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 3933b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId2 = mDbHelper.getContactId(rawContactId2); 39340c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 3935127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3936127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 3937127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 3938127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3939b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3940b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 394170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 3942627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 3943627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov boolean hasUnassignedContacts[] = new boolean[]{false}; 394470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 394570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 3946743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts); 3947743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 3948743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // Add a row to the ACCOUNTS table for each new account 3949743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 3950743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov if (!existingAccounts.contains(account)) { 3951743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 3952743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov + ", " + RawContacts.ACCOUNT_TYPE + ") VALUES (?, ?)", 3953743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov new String[] {account.name, account.type}); 3954743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 3955743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 395648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3957627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 3958743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // in the accountsToDelete set will be extra accounts whose data must be deleted. 3959627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 3960627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 3961627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 396270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 396370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 396470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 39655f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 3966627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 3967627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3968627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 3969627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 3970627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 3971627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3972627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 3973627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 3974627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "SELECT " + RawContacts._ID + 3975627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 3976627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3977627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 3978627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3979627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 3980627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3981627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 3982627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 3983627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 3984627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 3985627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 3986743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL( 3987743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 3988743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 3989743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + "=?", params); 3990627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3991627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3992627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (hasUnassignedContacts[0]) { 3993627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3994627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Account primaryAccount = null; 3995627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 399673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (isWritableAccount(account.type)) { 3997627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov primaryAccount = account; 3998627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov break; 3999627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4000627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4001627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4002627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (primaryAccount != null) { 4003627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {primaryAccount.name, primaryAccount.type}; 4004627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4005627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4006627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 4007627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + RawContacts.ACCOUNT_NAME + "=?," 4008627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=?" + 4009627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + 4010627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL", params); 4011627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4012627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // We don't currently support groups for unsynced accounts, so this is for 4013627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // the future 4014627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4015627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.GROUPS + 4016627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + Groups.ACCOUNT_NAME + "=?," 4017627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + Groups.ACCOUNT_TYPE + "=?" + 4018627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " IS NULL" + 4019627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " IS NULL", params); 4020743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 4021743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL( 4022743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 4023743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + 4024743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL"); 4025627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 402670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4027627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4028609cc5b4c96a6981f675a70ff743ecfec2b448e6Daniel Lehmann mDbHelper.updateAllVisible(); 4029609cc5b4c96a6981f675a70ff743ecfec2b448e6Daniel Lehmann 4030b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 403170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 403270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 403370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 403470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 403573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 403670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4037619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4038619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 4039627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 4040627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 4041743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov private void findValidAccounts(Set<Account> validAccounts, boolean[] hasUnassignedContacts) { 4042743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov Cursor c = mDb.rawQuery( 4043743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "SELECT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 4044743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " FROM " + Tables.ACCOUNTS, null); 4045627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4046627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 4047627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (c.isNull(0) && c.isNull(1)) { 4048627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov hasUnassignedContacts[0] = true; 4049627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } else { 4050627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 4051627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4052627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4053627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 4054627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 4055627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4056627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4057627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4058627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov /** 4059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 4060622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 406167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 406267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 406367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 406467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 406567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 406667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 406767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 406867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 406967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 407067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 407167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 407267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 4073dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 4074622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 4075dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 4076dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 4077622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4078622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4079dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 4080622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4081622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 40824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 40834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 40844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 4085bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 4086bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 4087bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 40880b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 4089b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 409035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4091d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 40921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 4093c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 4094c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4095619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 4096619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 4097a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 40984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 409935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 4100b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 410135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 410235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4103d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 4104763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4105619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 4106619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4107619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4108d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 41094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 4110763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 41114da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 41124da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 41136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 41146bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 41156bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 41165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 41175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 41185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 41195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 41205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 4121fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4122fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 41235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 41255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 41262d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill // TODO: pull this out into a method and generalize to not require contactId 41275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 41285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4129763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 41304da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String[] args; 41314da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (selectionArgs == null) { 41324da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[2]; 41334da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } else { 41344da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[selectionArgs.length + 2]; 41354da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 41364da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 41374da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args[0] = String.valueOf(contactId); 413860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 41394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 41404da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 41415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 41425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 41435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 41445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 41475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4149763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 41504da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 41514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 41524da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 41535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 41545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4156f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 4157f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 415842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 4159763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 4160f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 41614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 41624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 41634da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 4164f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 4165f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 4166f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 416742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 416842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 416942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 417042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return db.rawQuery( 417142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 417242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 417342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 417442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 417542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 417642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 4177ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 4178916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 4179ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 4180916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 4181ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4182916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet(qb, uri, projection, filterParam); 4183ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4184ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4185ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4186ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 4187ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 41884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 4189ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 4190d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 41914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 41924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4193e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 41945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 41954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 41964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 41974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4198763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4199ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 42005e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 42015e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 42025e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 42035e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar starredProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 42045e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar frequentProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 42055e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 42065e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 42074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 42084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 42094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 4210d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 42115e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 42125e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 42134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 4214d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4215d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 4216d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 4217763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 42184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 42194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 4220d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 42215e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 42225e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 4223d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 4224d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 42254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 4226d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4227d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 4228d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 4229d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 42304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 42314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 4232d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 4233d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 4234d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4235d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 4236d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4237d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4238ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 4239763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4240b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 424171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 42424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 4243b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4244b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 4245b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4246b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 4247d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 42484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 424982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 42504da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 42514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 42526bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 42536bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 425400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 4255ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 42563653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 425782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 42584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 42594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 42603653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 42613653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 42623653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 42633653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 42644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 426582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 426689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 42672815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 42682815f58f72f109790585931f601a63ddc02536a5Evan Millar } 42692815f58f72f109790585931f601a63ddc02536a5Evan Millar 427048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 427182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 42724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 427348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 42744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 427548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 427648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 427748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 4278ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 427982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 428089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 4281ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 42824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 42834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4284a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 42855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 42865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 42875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 42885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 42895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 42907318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 42915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 42925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 42945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 42955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 42965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 42975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 42985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 42995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 43005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 43015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 43025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 43035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 43045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 43055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 43065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 43075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4308a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 4309ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 43105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 4311a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4312a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4313a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 4314ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4315ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4316ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 43174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 431882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 431989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 43204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 43214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 43224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 432348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 432482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 43254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 43264da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 43274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 432848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 432948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 433048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 43315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 433282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 433389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 43344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 433508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 433608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String address = mDbHelper.extractAddressFromEmailAddress(email); 433708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 433808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 43394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 4340ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4341ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4342ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 43435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 434482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 434507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 434607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 434707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 434807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 434907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 435007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 435107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 43525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 435307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 435407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 435507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 435607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 435707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 435807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 435907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 436007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 436107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 436207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 436307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.DATA1 + " LIKE "); 436407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 436520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 436620938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 436720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 436807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 436907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov /* 437007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * Using a UNION instead of an "OR" to make SQLite use the right 437107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * indexes. We need it to use the (mimetype,data1) index for the 437207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * email lookup (see above), but not for the name lookup. 437307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * SQLite is not smart enough to use the index on one side of an OR 437407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * but not on the other. Using two separate nested queries 437507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * and a UNION between them does the job. 437607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov */ 437707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 437807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " UNION SELECT " + Data._ID + 437907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 438007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 438107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN "); 43827318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 438320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 43845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 43855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4386a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 43875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 43885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 4389a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4390a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4391a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 43925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 43935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 43945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 4395ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 439682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 439789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 439889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 4399ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4400ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4401ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 440248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 440382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 44044da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 440548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 440648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 44074da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 440848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 440948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 441048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 44115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 4412763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 44134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 44144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 44154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 44165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 44175ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 4418763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 44194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 44204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 44214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 44224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 44234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 44245ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 44255ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 442682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 44274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 44284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 4429e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4430e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4431e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 4432e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 443382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 4434e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4435e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4436e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 44374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 443882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 44394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 44404da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 4441a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 4442a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 4443a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 4444a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 44454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4446a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 4447a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 4448a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 4449e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 4450a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4451a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4452e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 4453b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 4454e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 4455e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 4456e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 4457e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 4458e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 4459a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 4460a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4461a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4462ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 4463b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4464ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 446589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4466ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4467ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4468ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4469ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 4470b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4471ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 44724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 44734da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 4474ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4475ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4476ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4477ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 4478b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 4479ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 448089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 448189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 4482ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4483ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4484ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4485b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 44860c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 4487b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 4488b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 4489b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4490b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 449131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 4492d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 44932d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 44942d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 44952d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 44962d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 449731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 4498d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 4499d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 450031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 450131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 450231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 450331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4504763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 45057581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 45067581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 45072d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 450831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 450931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4510eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 4511eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 4512eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 451389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4514e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4515e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 4516e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 4517b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 4518e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 451982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4520b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 4521e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4522e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 452382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4524b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 4525e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4526e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4527e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4528eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 4529eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 4530eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 453182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 45320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 45335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 45345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 45355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 453682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 45370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 45384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 45394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 45405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 45415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 45425ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 4543c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 4544a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 4545c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4546c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4547c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 45482d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 45492d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill return mGlobalSearchSupport.handleSearchShortcutRefresh(db, lookupKey, projection); 4550c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4551c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 45521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 4553b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 45541b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 45551b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 45561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 45571b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 4558b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 45591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 45601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 45611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 45621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 45631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 4564b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 45651b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 45661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 45671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 45681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 45691b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 4570b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 45711b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 457271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 45731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 45741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 45751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 457646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 457746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 457846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 457946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 458046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 458146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 458246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 458346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 45844da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 45854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 458646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 458746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 458846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 458909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 459009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 459109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 459209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 45934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 4594f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 4595c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 45964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 45974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 4598ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 4599ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 4600ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 4601ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov cursor = bundleLetterCountExtras(cursor, db, qb, selection, selectionArgs, sortOrder); 4602ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4603ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 46045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 46055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 46065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 46075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 46085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 4609038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 4610038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 4611038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 4612038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 46135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 46145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 46154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 46164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 46174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 46184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 46194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 46204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 462109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 462209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 462309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 462409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 462509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 462609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 462709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 462809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 462909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 463009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 463109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 463209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 463309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 463409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 463509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 463609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 463709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 4638bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 4639bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 4640bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 4641bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 4642ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4643bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 4644bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 4645ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 4646ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4647bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 4648bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 4649bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 4650bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4651de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 4652ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4653ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4654ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 4655ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 4656ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 4657ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 4658ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 4659ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder) { 4660ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 4661ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4662ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 4663ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 4664ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 4665ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 4666ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 4667ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 4668ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 4669ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 4670ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 4671ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 4672ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 4673ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4674ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 4675ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 4676ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4677ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4678bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 4679ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 4680bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 4681bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "SUBSTR(" + sortKey + ",1,1) AS " + AddressBookIndexQuery.LETTER); 4682bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4683bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 4684bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 4685bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 4686bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 4687bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 4688bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 4689bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 4690ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 4691bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "GET_PHONEBOOK_INDEX(SUBSTR(" + sortKey + ",1,1),'" + locale + "')" 4692bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 4693ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 4694ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov "COUNT(" + Contacts._ID + ") AS " + AddressBookIndexQuery.COUNT); 4695ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 4696ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4697f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 4698ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 4699ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 4700ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4701ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 4702f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 4703ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 4704ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 4705bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 4706bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 4707bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4708bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 4709bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 4710bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 4711ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 4712f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 4713bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 4714bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 4715bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 4716bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 4717bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 4718bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 4719bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 4720bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 4721bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4722bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4723bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4724bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 4725bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 4726bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 4727bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 4728bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4729bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 4730bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 4731bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 4732ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4733ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4734ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov final Bundle bundle = new Bundle(); 4735ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 4736f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 4737ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return new CursorWrapper(cursor) { 4738ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4739ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov @Override 4740ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov public Bundle getExtras() { 4741ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return bundle; 4742ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4743ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 4744ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 4745f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 4746ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4747ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4748ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 47492d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 475092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 475192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 475292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 475392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 47542d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 47552d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 47565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 47575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 47585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 475992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 476092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 476192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 476292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 476392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 476492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 476592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 476692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 476792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 476892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 476992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 477092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 477192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 477292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 477392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 477492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 477592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 477692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 477792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 47785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 47795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 47805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 47815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 47825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 47835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 47845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 47855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 47865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 47875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 47885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 47895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 47905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 47915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 47925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 47935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 47945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 47955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 47965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 47975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 47985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 47995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 48005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 48015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 48025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 48035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 48045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 48055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 480692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 48075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 48085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 48095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 48125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 48135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 48145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 48155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 48165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 48175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 48185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 48195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 48205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 48215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 48225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 48235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 48245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 482592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 482692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 48275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 48285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 48295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 48305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 48345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 48355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 48375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 48385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 484092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 484192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 48425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 48435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 48445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 48455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 48465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 484792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 48485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 48495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 48505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 48515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 48525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 485392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 48545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 485692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 485792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 485892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 485992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 48605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 48615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 486292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 486392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 486492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 48655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 486792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 486892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 48695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 487092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 487192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 487292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 487392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 487492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountType = c.getString(LookupByRawContactIdQuery.ACCOUNT_TYPE); 487592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 487692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 487792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 487892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 487992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 488092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 488192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 488292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 488392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 488492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 488592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 488692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 488792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 488892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 488992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 489092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 48915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 489392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 489492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 489592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 489692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 489792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 489892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 489992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 490092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 490192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 490292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 490392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 490492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 490592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 490692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 490792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_TYPE = 1; 490892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 490992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 491092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 491192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 491292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 491392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 49145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 49155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 49165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 49175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 491892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 491992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 49205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 49215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 49225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 49255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 49265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 49275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 49295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 49305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 49315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 49325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 49335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 49345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 49355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 49365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 49375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 49385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 493992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 494092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 494192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 49425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 49435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 49445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 49455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 49495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 49505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 49535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 495592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 495692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 495792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 495892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 495992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 496092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 496192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 496292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 496392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 496492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 496592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 4966ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 4967ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(db, rawContactId); 4968ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 4969ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 49705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 49715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 49725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 49735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 49745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 49755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 49775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 49785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 49805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 49815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 49835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 49845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 49855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 49865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 49875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 49885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 49895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 49905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 49915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 49925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 49945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 49955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 49995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 50005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 50015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 50025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 5005763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 5006763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 500782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5008916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 5009916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 5010916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 5011916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5012916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5013916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 5014916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 5015916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 5016916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 5017916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 5018916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String[] projection, String filter) { 5019916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5020916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5021916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 5022916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5023916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(" JOIN (SELECT " + 5024916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov RawContacts.CONTACT_ID + " AS snippet_contact_id"); 5025916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5026916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA_ID)) { 5027916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", " + DataColumns.CONCRETE_ID + " AS " 5028916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov + SearchSnippetColumns.SNIPPET_DATA_ID); 5029916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5030916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 50319c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA1)) { 50329c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA1 + " AS " + SearchSnippetColumns.SNIPPET_DATA1); 5033916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5034916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 50359c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA2)) { 50369c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA2 + " AS " + SearchSnippetColumns.SNIPPET_DATA2); 5037916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5038916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 50399c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA3)) { 50409c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA3 + " AS " + SearchSnippetColumns.SNIPPET_DATA3); 50419c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 50429c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov 50439c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA4)) { 50449c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA4 + " AS " + SearchSnippetColumns.SNIPPET_DATA4); 5045916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5046916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5047916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_MIMETYPE)) { 5048916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", (" + 5049916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov "SELECT " + MimetypesColumns.MIMETYPE + 5050916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " FROM " + Tables.MIMETYPES + 5051916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + MimetypesColumns._ID + "=" + DataColumns.MIMETYPE_ID + 5052916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov ") AS " + SearchSnippetColumns.SNIPPET_MIMETYPE); 5053916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5054916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5055916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS + 5056916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + DataColumns.CONCRETE_ID + 5057916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN ("); 5058916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5059916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // Construct a query that gives us exactly one data _id per matching contact. 5060916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // MIN stands in for ANY in this context. 5061916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append( 5062916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov "SELECT MIN(" + Tables.NAME_LOOKUP + "." + NameLookupColumns.DATA_ID + ")" + 5063916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5064916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5065916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " ON (" + RawContactsColumns.CONCRETE_ID 5066916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov + "=" + Tables.NAME_LOOKUP + "." + NameLookupColumns.RAW_CONTACT_ID + ")" + 5067916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + " GLOB '"); 5068916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(NameNormalizer.normalize(filter)); 5069916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 5070916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + ")" + 5071916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " GROUP BY " + RawContactsColumns.CONCRETE_CONTACT_ID); 5072916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5073916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(")) ON (" + Contacts._ID + "=snippet_contact_id)"); 5074916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5075916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 5076916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 5077916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5078916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5079916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void appendContactsTables(StringBuilder sb, Uri uri, String[] projection) { 5080763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 5081f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5082763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5083763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5084d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5085763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5086763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 5087b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 508882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 508982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 509082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 509182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 5092b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 509382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 509482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 509582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 509682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 509782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 50983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 50993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 5100a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 51013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 510282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 510382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 5104ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 5105763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 5106763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 5107763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 5108f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5109763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5110763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5111d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5112763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5113763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 5114763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 5115763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 5116763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 5117763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5118763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 511946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 512046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana // Note: currently, "export only" equals to "restricted", but may not in the future. 512146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana boolean excludeRestrictedData = readBooleanQueryParameter(uri, 512246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.FOR_EXPORT_ONLY, false); 512346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 5124f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 512546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 512646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana if (requestingPackage != null) { 512746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana excludeRestrictedData = excludeRestrictedData 512846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 512946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 513046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 513146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setProjectionMap(sRawContactsEntityProjectionMap); 513246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 513346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 513446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 513582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 513682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 513782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5138d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa // Note: currently, "export only" equals to "restricted", but may not in the future. 5139763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = readBooleanQueryParameter(uri, 5140d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa Data.FOR_EXPORT_ONLY, false); 5141763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 5142f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5143763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5144763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5145763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar excludeRestrictedData = excludeRestrictedData 5146d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5147763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5148763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 5149763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getDataView(excludeRestrictedData)); 515082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 515182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 51523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated presence when requested 5153b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 515482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 51553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 515682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 515782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 515882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 51593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated status updates when requested 5160b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 516182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 516282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 516382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 516482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 516582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 51663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 51673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 516882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 51693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 5170ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 51713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 51723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual presence when requested 51733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 51743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 51753296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdates.DATA_ID + "=" 51763296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 51773296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 51783296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 51793296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual status updates when requested 51803296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, 51813296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS, 51823296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_RES_PACKAGE, 51833296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_ICON, 51843296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_LABEL, 51853296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_TIMESTAMP)) { 51863296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 51873296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 51883296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 51893296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 51903296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 519182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 519282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 519382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 5194ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 5195ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 51960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 51970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 51980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5199b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 52000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 52010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 5202b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 52030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 52040a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 52050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 52060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 52070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 5208b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 52090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 52100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 52110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 52120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 52130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 52140a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 52150a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 52160a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 52170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 52180a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setTables(sb.toString()); 52190a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 52200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 52210a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 52224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 5223f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 5224f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 5225e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5226e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 5227e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 5228e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 5229fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 5230fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 5231e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 5232e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5233e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 5234e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 5235e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 5236e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 52374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 52384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 52394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 52404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 52414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 52424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 52434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 52444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 52454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5246e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 5247f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 5248f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 5249e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5250e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 5251e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 5252e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 5253fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 5254fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 5255e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 5256e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5257e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 5258e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 5259e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 5260e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 5261e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 5262e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 5263e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 5264e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 5265e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 5266e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 5267e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 5268e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 5269e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5270e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 5271e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 5272e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 5273e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5274e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5275e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 52767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 5277c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 5278c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 5279c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 5280c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 5281c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 5282f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 5283f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String limitParam = getQueryParameter(uri, "limit"); 5284c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 5285c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5286c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5287c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 5288c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 5289c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 5290c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 5291c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 5292c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5293c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5294c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 5295c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 5296c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 5297c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5298c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5299c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5300c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 53015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 53025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 53035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 53045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 53055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 53065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 53075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 53085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 53095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 53105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 53115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 53125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 53135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 53155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 53165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 53175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 53195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 53205e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53215e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 53225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 53235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 53255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 53265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 53285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 53295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 533100ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 5332d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 533370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 533470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 5335fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0"; 533670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 533770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 533870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 533970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 5340d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 534170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 534267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 53435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 53445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 5345619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5346619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5347619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 5348b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 5349b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 5350b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 5351b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 5352d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 5353e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov return openPhotoAssetFile(uri, mode, 5354e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=" + Contacts.PHOTO_ID + " AND " + RawContacts.CONTACT_ID + "=?", 5355e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 5356e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5357b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5358e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 5359e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov return openPhotoAssetFile(uri, mode, 5360e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=? AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'", 53614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 5362d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5363d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5364f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 536542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 536642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann mSelectionArgs1[0] = String.valueOf(lookupContactIdByLookupKey(mDb, lookupKey)); 536742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + "=?"; 536842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 536942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 537042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 537142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 537242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 537342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann outputRawContactsAsVCard(localStream, selection, mSelectionArgs1); 537442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return buildAssetFileDescriptor(localStream); 537542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 537642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 537742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 537842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 537942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 538042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 538142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 538242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String[] selectionArgs = new String[loopupKeyList.length]; 538342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 538442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann selectionArgs[index] = 538542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String.valueOf(lookupContactIdByLookupKey(mDb, lookupKey)); 538642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 538742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append("(?"); 538842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 538942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(",?"); 539042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 539142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 539242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 539342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 539442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 5395d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5396d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 5397d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 5398d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 5399d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 540042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann outputRawContactsAsVCard(localStream, selection, selectionArgs); 5401d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 5402d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5403b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5404b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 5405fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("File does not exist", 5406fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov uri)); 5407b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5408b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5409b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5410e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov private AssetFileDescriptor openPhotoAssetFile(Uri uri, String mode, String selection, 5411e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String[] selectionArgs) 5412e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 5413e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 5414e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("Mode " + mode 5415e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 5416e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5417e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 5418e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 5419e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 5420e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 5421e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 5422e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, 5423e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov selectionArgs); 5424e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5425e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 5426d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 5427d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5428d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5429d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 5430d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 5431d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5432d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 5433d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 5434d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 5435d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 5436d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5437d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 5438d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 5439d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5440d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 5441d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 5442d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 5443b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5444d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 5445d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 5446d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 5447d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5448d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 5449d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5450d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5451d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5452d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 5453d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 5454d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 5455d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5456d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 5457d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 5458d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 54597a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 54607a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa new VCardComposer(context, VCardConfig.VCARD_TYPE_DEFAULT, false); 5461d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 5462d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5463f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 54647a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa if (!composer.init(selection, selectionArgs)) { 54657a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 5466d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 54677a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa } 5468d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5469d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 5470d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 5471d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 5472d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5473d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5474d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 5475d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5476b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 54774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 54784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 5479a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 54804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 5481b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 5482be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 54832d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 5484b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 5485b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 5486b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 5487f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 548842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 5489f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 5490b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 5491be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 5492b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 5493b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 5494508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 5495b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 549648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 549748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 549848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 549948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 55009005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 55019005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 550248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 550348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 550448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 550548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 550648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 550748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 550848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 550948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 5510b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 5511b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 5512b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 5513b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 5514b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 5515b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 5516b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 5517b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 5518c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 5519c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 5520c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 5521c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 5522d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov 552361efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 552461efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 55254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 55264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 55277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 55285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void setDisplayName(long rawContactId, int displayNameSource, 55295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary, String displayNameAlternative, String phoneticName, 55305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int phoneticNameStyle, String sortKeyPrimary, String sortKeyAlternative) { 55315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(1, displayNameSource); 55325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 2, displayNamePrimary); 55335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 3, displayNameAlternative); 55345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 4, phoneticName); 55355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(5, phoneticNameStyle); 55365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 6, sortKeyPrimary); 55375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 7, sortKeyAlternative); 55385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(8, rawContactId); 553925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 55403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 55413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 554273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 554373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 554473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 554573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 5546a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.add(rawContactId); 554773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 554873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 5549c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 5550c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 5551c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 5552c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 5553c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 5554c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 5555653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 5556c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 5557653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 5558653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 5559c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 5560c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 5561c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 5562c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 5563c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 5564c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 5565c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 5566c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 5567c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 5568653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 5569c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 5570653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 5571653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 5572c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 5573c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 5574ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 5575813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public String insertNameLookupForEmail(long rawContactId, long dataId, String email) { 5576f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 5577813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 5578f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5579f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5580b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String address = mDbHelper.extractHandleFromEmailAddress(email); 5581b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (address == null) { 5582813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 5583f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5584f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5585f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 5586f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 5587813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return address; 5588f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5589f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5590f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5591f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 5592f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5593f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 5594f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 5595f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 5596f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5597f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5598f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 5599f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 5600f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5601f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5602a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 5603a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 5604a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 5605a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 5606a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 5607a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5608a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 5609a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 5610a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 5611a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5612a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5613f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5614d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name, 5615d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov int fullNameStyle) { 5616d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle); 5617f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5618f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5619f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 5620f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5621f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 5622f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 5623f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5624f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5625f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5626f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 5627f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 5628f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 5629f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5630f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5631f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5632f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 5633d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 5634f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5635f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5636f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 563748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov public void insertNameLookupForPhoneticName(long rawContactId, long dataId, 563848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov ContentValues values) { 563948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (values.containsKey(StructuredName.PHONETIC_FAMILY_NAME) 564048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov || values.containsKey(StructuredName.PHONETIC_GIVEN_NAME) 564148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov || values.containsKey(StructuredName.PHONETIC_MIDDLE_NAME)) { 564248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, 564348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_FAMILY_NAME), 564448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_MIDDLE_NAME), 564548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_GIVEN_NAME)); 564648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 564748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 564848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 564948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov public void insertNameLookupForPhoneticName(long rawContactId, long dataId, String familyName, 565048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov String middleName, String givenName) { 565148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.setLength(0); 565248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (familyName != null) { 565348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(familyName.trim()); 565448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 565548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (middleName != null) { 565648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(middleName.trim()); 565748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 565848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (givenName != null) { 565948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(givenName.trim()); 566048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 566148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 566248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (mSb.length() > 0) { 566348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookup(rawContactId, dataId, NameLookupType.NAME_COLLATION_KEY, 566448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov NameNormalizer.normalize(mSb.toString())); 566548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 566648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 566748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 5668f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5669f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 5670f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5671f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 56725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(1, rawContactId); 56735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(2, dataId); 56745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(3, lookupType); 56755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mNameLookupInsert, 4, name); 5676f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 5677f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5678f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5679f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5680f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 5681f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5682f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 56835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupDelete.bindLong(1, dataId); 5684f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 5685f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5686f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 56872d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 5688d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5689d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 5690d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 5691d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 5692d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 5693d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 5694d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 5695e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 5696916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 5697916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 5698e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 5699e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 57005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 5701c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 57027318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam); 5703c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 5704c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5705c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 57067318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam) { 57077318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), true); 57085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 57095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 57105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 57117318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov boolean allowEmailMatch) { 5712d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5713dc947a9d03279eab0fb7c3b9d8ffbb492c1e2062Dmitri Plotnikov "SELECT " + NameLookupColumns.RAW_CONTACT_ID + 5714d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5715d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 5716d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 57175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 5718a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 5719a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 5720a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 57214cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao + NameLookupType.NAME_SHORTHAND + "," 5722f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee + NameLookupType.ORGANIZATION + "," 572389f1f71495aedc58252b3f58a46a036986c319d2Dmitri Plotnikov + NameLookupType.NAME_CONSONANTS); 572420938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 572520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 572620938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 572789f1f71495aedc58252b3f58a46a036986c319d2Dmitri Plotnikov sb.append("))"); 5728ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5729ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 57304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 57314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 57324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 57334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 5734b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 5735b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 5736b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 5737b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 5738b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 57394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 57404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 5741b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 5742b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5743b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5744caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 57455e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 57465e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 57475e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 57485e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 57495e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 57505e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 57515e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 57525e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 57535e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 57545e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 57555e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5756caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 5757caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 5758caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 5759df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 5760df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 5761caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 5762caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 5763caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5764caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 57656f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 5766caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 57676f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 5768caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5769f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 577073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 577173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov * Returns true if the specified account type is writable. 577273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 577373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov protected boolean isWritableAccount(String accountType) { 5774bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov if (accountType == null) { 5775bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 5776bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 5777bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 577873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov Boolean writable = mAccountWritability.get(accountType); 577973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 578073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 578173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 578273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 5783627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 5784627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 5785627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 5786627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 578773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov accountType.equals(sync.accountType)) { 578873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 578973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 5790627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5791627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5792627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 5793627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 5794627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 579573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 579673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 579773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 579873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 579973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 580073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.put(accountType, writable); 580173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 5802627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5803b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 5804f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 5805f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 5806f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5807f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 5808f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5809f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5810f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5811f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5812f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5813f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 5814f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5815f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5816f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5817f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5818f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 5819f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5820f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 5821f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 5822f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5823f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5824f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 5825f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 5826f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 5827f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 5828f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 5829f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5830f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5831f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 5832f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 5833f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 5834f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 5835f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5836f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5837f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5838f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5839f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5840f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 5841f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 5842f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5843f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 5844f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 5845f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 5846f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 5847f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5848f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5849f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5850f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5851f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 5852f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5853f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 5854f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5855f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5856f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5857f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 5858f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 5859f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 5860f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5861f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5862f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5863f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 5864f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 5865f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 5866f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 5867f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 5868f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5869f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5870f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 5871f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 58725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 58735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindString(SQLiteStatement stmt, int index, String value) { 58745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 58755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 58765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 58775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindString(index, value); 58785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 58795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 58805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 58815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindLong(SQLiteStatement stmt, int index, Number value) { 58825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 58835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 58845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 58855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindLong(index, value.longValue()); 58865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 58875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 58884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 5889