ContactsProvider2.java revision 2a0d5f9c628e723261bc5198e0fd606076b76b74
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; 61b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 624cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Taoimport android.content.res.Configuration; 631129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikovimport android.database.CharArrayBuffer; 644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 65ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.CursorWrapper; 66ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 6709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor; 6809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor.RowBuilder; 69a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 70b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 73c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 7551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikovimport android.os.AsyncTask; 766ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 77d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 78b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 792a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikovimport android.os.SystemClock; 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 150c64e0fb0655d8e81c22db555b55c953b5b787b01Fred Quintana private static final String GOOGLE_MY_CONTACTS_GROUP_TITLE = "System Group: My Contacts"; 1513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 152b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov * Property key for the legacy contact import version. The need for a version 1533d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1543d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1553d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 156b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final String PROPERTY_CONTACTS_IMPORTED = "contacts_imported_v1"; 157b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int PROPERTY_CONTACTS_IMPORT_VERSION = 1; 15851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final String PREF_LOCALE = "locale"; 1593d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1602a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov private static final String PROPERTY_AGGREGATION_ALGORITHM = "aggregation_v2"; 1612a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov private static final int PROPERTY_AGGREGATION_ALGORITHM_VERSION = 2; 1622a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 1630e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1640e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 165a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1675e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final String TIMES_CONTACED_SORT_COLUMN = "times_contacted_sort"; 1685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 169d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 1705e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar + TIMES_CONTACED_SORT_COLUMN + " DESC, " 1719b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 172d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 173d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 174d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 175d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1766e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 1779b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 1789b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1799b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 1809b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 1816e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 1829b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 1839b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1849b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 1859b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 186de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 187de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 188d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 189d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 198f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 19942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann private static final int CONTACTS_AS_MULTI_VCARD = 1011; 2004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 2025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 2035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 20446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 2054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2066bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 208ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 20948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 21048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 21148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 21248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 21348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 21448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 21548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 21648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 217a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2186bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 2196bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 220b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 221b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 222b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 22382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 22482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 2251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 22631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 22731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 228eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 229eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 230ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 231ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 232ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 233ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 23435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 235b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 23635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 237c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 238c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 239c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2401b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2411b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2421b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2431b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2441b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 24546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 24646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 24709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 24809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 249d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 250f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 251f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 252f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 25367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 25467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2556cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 257f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 258ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 259ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 260d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 26167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 262d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 263ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2641f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 26514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 26667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 273f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 27488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 27588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 27688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 27788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 27888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 27988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 28088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 281f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 2823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 28414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 2853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 288f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 2893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 29114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 292321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 29320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 29420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 295321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 296321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 29720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 29820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 299f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 30019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 30119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 30219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 30319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 304ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 305ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 306ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 30719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 30819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 30919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 310ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 311ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 31219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 31319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 314c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 315df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 316caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 31771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 31871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 31971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 32071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 32171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 32271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 32371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 32471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 32571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 32671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 32771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 32871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 32971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 33071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 331a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 332a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 333a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 334a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 335a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 336a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 337a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 338a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 339a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 340a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 341a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 342a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 343916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 344916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 345916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 346916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 347916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NICKNAME + "," + 348916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_SHORTHAND + "," + 349f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.ORGANIZATION + "," + 350f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.NAME_CONSONANTS; 351916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 352916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 353038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 354038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 355e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 357916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 358916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final HashMap<String, String> sContactsProjectionWithSnippetMap; 359916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 3605e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 3615e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentStarredProjectionMap; 3625e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentFrequentProjectionMap; 363f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 364f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final HashMap<String, String> sContactsVCardProjectionMap; 365ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 366d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 36746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** Contains the columns from the raw contacts entity view*/ 36846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final HashMap<String, String> sRawContactsEntityProjectionMap; 3694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3739261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 374e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 375ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 376ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 377ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 378ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 379373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 380b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 381eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 382eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 38382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 38482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 3851b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 3861b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 3877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 3899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 3909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 3919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 3929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 3939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 3942526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 3952526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 396bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 397bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 398bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 399bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 40051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 401c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 402c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 4033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 404c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 4053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 40625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 40782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 408a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 409f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 410f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 411a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 412a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 413a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 4140a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 415a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 416f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov private SQLiteStatement mResetNameVerifiedForOtherRawContacts; 417a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 418f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 419f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 4201129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdStructuredName; 4211129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdOrganization; 4221129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdNickname; 4231129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdPhone; 424f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 4251129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 4261129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 4272526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 4282526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 429f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 430f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 4314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 4324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 433a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 434d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 435d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 436d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 4373653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 4383653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 4392d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 4402d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 4413653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 4425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 4435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 4445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 445f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 44642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 44742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 4485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 449ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 450ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 4515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 4523653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 45646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 45746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 45846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 459b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 462ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 46348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 465ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 46748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 471ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 47248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4731f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 474ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 475ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 476ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 477ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 47835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 479b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 480b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 48135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 482a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 483b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 484b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 485b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 486b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 488eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 489eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 49082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 49182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 4921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 493c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 494c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 495c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 496c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 4972d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 498c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 499c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 5001b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 5011b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 5021b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 5031b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 5041b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 5051b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 5061b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 5071b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 50809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 50909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 51019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 51119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 51219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 513038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 514038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 515e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 5164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 5174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 5185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME_PRIMARY); 5195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 5205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 5215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 5225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 5235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 5245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 5255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, Contacts.SORT_KEY_ALTERNATIVE); 5264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 5304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 5314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 532f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 5334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 535f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 5363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 5373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 5383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 539aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori addProjection(sContactsProjectionMap, Contacts.CONTACT_CHAT_CAPABILITY, 540aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY); 5413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 5423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 5433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 5443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 5453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 5463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 5473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 5483296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 5493296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 5503296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 5513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 552916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap = new HashMap<String, String>(); 553916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.putAll(sContactsProjectionMap); 554916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_MIMETYPE, 555916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov SearchSnippetColumns.SNIPPET_MIMETYPE); 556916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA_ID, 557916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA_ID); 5589c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA1, 5599c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA1); 5609c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA2, 5619c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA2); 5629c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA3, 5639c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA3); 5649c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA4, 5659c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA4); 566916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5675e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5695e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Long.MAX_VALUE + " AS " + TIMES_CONTACED_SORT_COLUMN); 5705e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5715e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5725e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5735e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Contacts.TIMES_CONTACTED + " AS " + TIMES_CONTACED_SORT_COLUMN); 5745e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 575f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap = Maps.newHashMap(); 576f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 577d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 578ba355248c255551bc65d8023b968513cbe9bcdf3Jeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "NULL AS " + OpenableColumns.SIZE); 5794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 5814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 5824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 5834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 5844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 5854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 5864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 5874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 5884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 5895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_PRIMARY, 5905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY); 5915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, 5925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE); 5935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_SOURCE, 5945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE); 5955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.PHONETIC_NAME, 5965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME); 5975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.PHONETIC_NAME_STYLE, 5985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE); 599f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.NAME_VERIFIED, 600f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov RawContacts.NAME_VERIFIED); 6015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SORT_KEY_PRIMARY, 6025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY); 6035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SORT_KEY_ALTERNATIVE, 6045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE); 6054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 6064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 6074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 6084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 6094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 6104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 6114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 6124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 6134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 6144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 6154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 6162815f58f72f109790585931f601a63ddc02536a5Evan Millar 6174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 6184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 6194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 6204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 6214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 6224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 6234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 6244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 6254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 6264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 6274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 6284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 6294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 6304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 6314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 6324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 6334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 6344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 6354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 6364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 6374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 6384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 6394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 6404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 6414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 6424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 6434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 64482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 6454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 6464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 6474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 6484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 6494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 650f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov sDataProjectionMap.put(RawContacts.NAME_VERIFIED, RawContacts.NAME_VERIFIED); 65156d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 6524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 6535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 6545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 6555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 6565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 6575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 6585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 6595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, Contacts.SORT_KEY_ALTERNATIVE); 6604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 6614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 6624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 6634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 6644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 6654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 666a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 667afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann sDataProjectionMap.put(Contacts.NAME_RAW_CONTACT_ID, Contacts.NAME_RAW_CONTACT_ID); 6684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 669a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 67046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana HashMap<String, String> columns; 67146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns = new HashMap<String, String>(); 67246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts._ID, RawContacts._ID); 67346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 67446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 67546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 67646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 67746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.VERSION, RawContacts.VERSION); 67846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 67946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DELETED, RawContacts.DELETED); 680bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey columns.put(RawContacts.IS_RESTRICTED, RawContacts.IS_RESTRICTED); 68146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 68246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 68346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 68446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 685f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov columns.put(RawContacts.NAME_VERIFIED, RawContacts.NAME_VERIFIED); 68646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 68746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.MIMETYPE, Data.MIMETYPE); 68846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA1, Data.DATA1); 68946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA2, Data.DATA2); 69046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA3, Data.DATA3); 69146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA4, Data.DATA4); 69246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA5, Data.DATA5); 69346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA6, Data.DATA6); 69446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA7, Data.DATA7); 69546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA8, Data.DATA8); 69646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA9, Data.DATA9); 69746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA10, Data.DATA10); 69846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA11, Data.DATA11); 69946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA12, Data.DATA12); 70046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA13, Data.DATA13); 70146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA14, Data.DATA14); 70246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA15, Data.DATA15); 70346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC1, Data.SYNC1); 70446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC2, Data.SYNC2); 70546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC3, Data.SYNC3); 70646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC4, Data.SYNC4); 70746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 70846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.STARRED, Data.STARRED); 70946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 71046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 71146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 71246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 71346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana sRawContactsEntityProjectionMap = columns; 71446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 7153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 7163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 7173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 718aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori addProjection(sContactsProjectionMap, Contacts.CONTACT_CHAT_CAPABILITY, 719aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY); 7203296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 7213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 7223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 7233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 7253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 7273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 7293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 7303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 7323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.PRESENCE, 7333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 734aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori addProjection(sDataProjectionMap, Data.CONTACT_CHAT_CAPABILITY, 735aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY); 7363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS, 7373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 7383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 7393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 7413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_LABEL, 7433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_ICON, 7453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 7463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 7485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 7495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 7505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 7515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 7525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 7535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 7545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 7555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 7565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 7575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 7585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 7595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 7605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 7615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 7625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 7635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 7645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 7655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 7665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 7675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 7685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 7695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 7705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 7715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 7725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 7735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 7745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 7755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 7768f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 7775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 7785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 7795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 7805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 7815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 7825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 7835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 7845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, 7855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.SORT_KEY_ALTERNATIVE); 7865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 7875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 7885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 7895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 7905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 7915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 792a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 7935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 7945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 7955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 7963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 7973296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 7983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 799aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_CHAT_CAPABILITY, 800aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY); 8013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 8023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 8033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 8043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 8053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 8063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 8073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 8083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 8093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 8103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 8113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 8123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 8133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 8143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 815aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori addProjection(sDistinctDataProjectionMap, Data.CHAT_CAPABILITY, 816aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori Tables.PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY); 8173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS, 8183296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 8193296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 8203296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 8213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 8223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 8233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 8243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 8253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 8263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 8273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 828e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 829e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 830fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts._ID 831fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup._ID); 83256d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 833fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LOOKUP_KEY 834fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.LOOKUP_KEY); 835e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 836fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.DISPLAY_NAME 837fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.DISPLAY_NAME); 838e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 839fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LAST_TIME_CONTACTED 840e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 841e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 842fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.TIMES_CONTACTED 843fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.TIMES_CONTACTED); 844e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 845fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.STARRED 846fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.STARRED); 847e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 848fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.IN_VISIBLE_GROUP 849fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 850e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 851fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.PHOTO_ID 852fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.PHOTO_ID); 853e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 854fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.CUSTOM_RINGTONE 855fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.CUSTOM_RINGTONE); 856e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 857fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.HAS_PHONE_NUMBER 858fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 859e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 860fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.SEND_TO_VOICEMAIL 861e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 862e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 863e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 864e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 865e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 866e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 867e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 8689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 869ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 870ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 87189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 872035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 873035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 8749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 8759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 8769261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 87789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 878ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 87967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 880ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 8813cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 88294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 8833cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 88438446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 88589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 88689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 88789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 88889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 889ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 890ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 8916cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 892ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 893ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 894d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 895d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 896ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 897ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 898ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 899d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 900d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 901ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 902f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 903ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 904ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 905b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 906b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 907b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 908b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 9090c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 9100c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 911b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 912b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 913eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 914eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 915eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 916eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 917eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 918eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 919341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 920341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 921341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 922fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 923341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 924341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 925341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 92668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 92768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 92868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 92968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 93068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 931e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 93268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 93368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 93468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 935eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 936eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 937373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 9384dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 9390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 9400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 94182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 94282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 94382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 94470c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 94570c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 94682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 94782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 94882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 94982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 950aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori columns.put(StatusUpdates.CHAT_CAPABILITY, StatusUpdates.CHAT_CAPABILITY); 9510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 9520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 9530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 9540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 9550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 95682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 95719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 9581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 9591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 9601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 9611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 9621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 9631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 9641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 9651b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 9661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 9671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 9684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 9694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 9703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 9713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey map.put(toField, fromField + " AS " + toField); 9723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 9733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 9743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 9763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 9783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 980653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 9813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9821129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov @SuppressWarnings("all") 9833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 9843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 985a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 986a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 987a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 988a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 989a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 990a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 991a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 992a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 9933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 995653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 996653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 997b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 998653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 999653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 1000653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1001653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 10023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 10033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 10043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 10055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1006e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 1007e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1008e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 1009e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 1010653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 1011e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1012e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1013e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 10143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 10173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 10183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 1019813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * 1020813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * @return true if update changed something 10213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1022813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1023f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 102414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 102514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1026653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1027653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 1028653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 1029653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 1030653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 1031653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1032653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 1033653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 1034653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 1035653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 1036653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 1037653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1038653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 1039653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 1040653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1041653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1042653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 10434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " =?", mSelectionArgs1); 1045653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1046653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1047f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1048653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 1049653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1050813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1051813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 10523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 105514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 105614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 105714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 10584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=?", mSelectionArgs1); 10604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 10614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=?", mSelectionArgs1); 10623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 10635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 10643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 10663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 10694da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov long mimeTypeId = getMimeTypeId(); 1070e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 1071e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 10724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 10734da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = db.query(DataDeleteQuery.TABLE, 10744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov DataDeleteQuery.CONCRETE_COLUMNS, 10754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Data.RAW_CONTACT_ID + "=?" + 10764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov " AND " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId, 10774da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 10783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 1079e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 108014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 1081f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 1082e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 1083e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 1084e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 1085e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 10863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 10883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 10893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10904da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (primaryId != -1) { 10914da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov setIsPrimary(rawContactId, primaryId, mimeTypeId); 10924da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 1093e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1094e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1095e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 1096e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 1097e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 1098e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 1099e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1100e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 11013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 110325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 1104285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1105d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(db, rawContactId); 1106fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(db, rawContactId); 1107285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 11083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1109a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1110622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1111622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 1112813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * as baseline, but augmented with any updates. Returns null if there is 1113813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * no change. 1114622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1115622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 1116622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 1117813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov boolean changing = false; 1118622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 11194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 11204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=?", 11214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 1122622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 1123622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 1124622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 1125622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 1126813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov final String value = cursor.getString(i); 1127813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!changing && update.containsKey(key)) { 1128813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov Object newValue = update.get(key); 1129813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String newString = newValue == null ? null : newValue.toString(); 1130813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov changing |= !TextUtils.equals(newString, value); 1131813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1132813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov values.put(key, value); 1133622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1134622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1135622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 1136622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 1137622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1138813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!changing) { 1139813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 1140813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1141813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1142622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 1143622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 1144622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 11483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 11503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 11513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1155622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 11563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1157622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 11583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1159622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 11603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1164622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 116514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 116614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 116714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1168f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1169d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov Integer fullNameStyle = values.getAsInteger(StructuredName.FULL_NAME_STYLE); 1170d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name, 117151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov fullNameStyle != null 117251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov ? mNameSplitter.getAdjustedFullNameStyle(fullNameStyle) 117351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov : FullNameStyle.UNDEFINED); 117448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, values); 117525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1176813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 117714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 117814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 117914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 118014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1181813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1182f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1183622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1184622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1185cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1186622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1187813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1188813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1189813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1190813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1191622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 119214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1193f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 11947ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME) || 11957ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov values.containsKey(StructuredName.PHONETIC_FAMILY_NAME) || 11967ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov values.containsKey(StructuredName.PHONETIC_MIDDLE_NAME) || 11977ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov values.containsKey(StructuredName.PHONETIC_GIVEN_NAME)) { 11987ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov augmented.putAll(values); 11997ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov String name = augmented.getAsString(StructuredName.DISPLAY_NAME); 1200f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 12017ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov Integer fullNameStyle = augmented.getAsInteger(StructuredName.FULL_NAME_STYLE); 1202d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name, 120351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov fullNameStyle != null 120451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov ? mNameSplitter.getAdjustedFullNameStyle(fullNameStyle) 120551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov : FullNameStyle.UNDEFINED); 12067ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, augmented); 120714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 120825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1209813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1210813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 121114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 121214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 121314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 121414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 121514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 121614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 121714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 121814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 121914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1220f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 122125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1222813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 122314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 12243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1227622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 12283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1229622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1230622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1231622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1232622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 12333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1234622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1235622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1236622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1237622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1238622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1239622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1240622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 124167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1242622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 124367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 124467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1245622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1246622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 12478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1248622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1249622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 125067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 125167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 125267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 125367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 125467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 125567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 12568c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1257622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 12584cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao // As the name could be changed, let's guess the name style again. 12594cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao name.fullNameStyle = FullNameStyle.UNDEFINED; 12604cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mSplitter.guessNameStyle(name); 1261ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao int unadjustedFullNameStyle = name.fullNameStyle; 1262ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao name.fullNameStyle = mSplitter.getAdjustedFullNameStyle(name.fullNameStyle); 12635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov final String joined = mSplitter.join(name, true); 1264622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 12655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 1266ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao update.put(StructuredName.FULL_NAME_STYLE, unadjustedFullNameStyle); 12675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, name.phoneticNameStyle); 12684cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } else if (touchedUnstruct && touchedStruct){ 1269d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov if (!update.containsKey(StructuredName.FULL_NAME_STYLE)) { 1270d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov update.put(StructuredName.FULL_NAME_STYLE, 1271d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mSplitter.guessFullNameStyle(unstruct)); 12724cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1273d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov if (!update.containsKey(StructuredName.PHONETIC_NAME_STYLE)) { 1274d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, 1275d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mSplitter.guessPhoneticNameStyle(unstruct)); 12764cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1277622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1278622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1279622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1280622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1281622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1282622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1283622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1284622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1285622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1286622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1287622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1288622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1289622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1290622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1291622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1292622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1293622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1294622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1295622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1296813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1297f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1298622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1299622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1300813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1301813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1302813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1303813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1304622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1305f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1306813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 1307622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1308622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1309622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1310622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1311622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1312622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1313622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1314622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1315622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1316622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1317622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1318622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1319622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1320622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1321622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1322622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1323622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1324622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 132567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 132667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 132767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 132867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1329622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1330622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1331622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1332622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1333622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1334622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 133567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 133667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 133767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1338622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1339622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1340622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 13413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 13463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 13483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 13493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 13513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 13523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 13533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 13543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1358622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1359622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1360622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1362622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1363813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1364f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1365622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1366622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1367813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1368813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1369813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1370622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1371813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return super.update(db, values, c, callerIsSyncAdapter); 1372622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1374622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1375622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1376622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1377622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1378622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1379622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1380622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1381622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 13823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1383622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1384622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1385622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1386622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1387622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 13923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 13943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 13953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1399a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1400a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1401a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1402a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1403a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 140425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1405a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1406a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 14073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 1410813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1411f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1412813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1413813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1414813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 141514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 141631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov boolean containsCompany = values.containsKey(Organization.COMPANY); 141731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov boolean containsTitle = values.containsKey(Organization.TITLE); 141831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsCompany || containsTitle) { 1419813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1420813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1421813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 142231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov String company; 142331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 142431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsCompany) { 142531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov company = values.getAsString(Organization.COMPANY); 142631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } else { 142731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 142831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov company = DatabaseUtils.stringForQuery(db, 142931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov "SELECT " + Organization.COMPANY + 143031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " FROM " + Tables.DATA + 143131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " WHERE " + Data._ID + "=?", mSelectionArgs1); 143231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 143331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 143431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov String title; 143531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsTitle) { 143631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov title = values.getAsString(Organization.TITLE); 143731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } else { 143831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 143931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov title = DatabaseUtils.stringForQuery(db, 144031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov "SELECT " + Organization.TITLE + 144131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " FROM " + Tables.DATA + 144231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " WHERE " + Data._ID + "=?", mSelectionArgs1); 144331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 144431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 144531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov deleteNameLookup(dataId); 144631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov insertNameLookupForOrganization(rawContactId, dataId, company, title); 144731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 144831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 144931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 1450813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 145114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 145214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 145314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 145414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1455a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 145614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 145714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 145814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 145925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1460a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 146114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 146214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 146314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 14653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 14663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 14673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 14683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 14693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 14703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 14713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1475e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1476e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1477e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1478e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1479e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1480e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1481e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 14825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1483813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String email = values.getAsString(Email.DATA); 148414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 148514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 148614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 148725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1488813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String address = insertNameLookupForEmail(rawContactId, dataId, email); 1489813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (address != null) { 1490813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1491813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 149214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 149314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 149414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 149514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1496813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1497f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1498813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1499813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1500813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 150114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1502b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (values.containsKey(Email.DATA)) { 1503813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1504813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1505813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1506b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String address = values.getAsString(Email.DATA); 1507b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov deleteNameLookup(dataId); 1508b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 1509b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1510813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1511b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov } 1512813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1513813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 151414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 151514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 151614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 151714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 151814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 151914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 152014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 152114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 152214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1523f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 152425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1525813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 152614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1527e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1528e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1529e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1530e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1531e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1532e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1533e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1534e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1535e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1536e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1537e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1538e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1539e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1540e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 154114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 154214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 154314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 154414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 154514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 154614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 154714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 154814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 154914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 155014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 155114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 155214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1553813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!TextUtils.isEmpty(nickname)) { 1554813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1555813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1556813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1557813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 155814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 155914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 156014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 156114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1562813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1563f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 156414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 156514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 156614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1567813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1568813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1569813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 157014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1571b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (values.containsKey(Nickname.NAME)) { 1572b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 1573b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov deleteNameLookup(dataId); 1574b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1575b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1576813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1577b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov } 1578813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1579813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 158014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 158114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 158214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 158314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 158414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 158514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 158614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 158714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 158814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1589f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 159025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1591813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 159214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 159314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 159414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 159514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 15963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 15973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 15993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 16003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 16023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 16035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 16040b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 16050b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 16060b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 1607813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number); 1608813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 16090b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1610653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 16110b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1612285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 161325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1614813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (normalizedNumber != null) { 1615813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1616813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 16170b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 16180b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 16190b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1620653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1621653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1622653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1623653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1624813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1625f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1626813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String number = null; 1627813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String normalizedNumber = null; 16280b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 1629813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov number = values.getAsString(Phone.NUMBER); 1630813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov normalizedNumber = computeNormalizedNumber(number); 1631813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1632813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1633653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1634813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1635813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1636813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1637653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1638813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 1639813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1640813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 16410b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1642285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 164325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1644813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 16450b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1646813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 164714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 164814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 164914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 165014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 165114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 165214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 165314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 165414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 165514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 165614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1657285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 165825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1659813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 166014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1661653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1662653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1663813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov private String computeNormalizedNumber(String number) { 1664e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1665e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1666e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1667e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1668653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1669653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1670e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1671653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1672653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1673e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1674653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 16755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1676653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1677e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 167836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.MIN_MATCH, 167936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov PhoneNumberUtils.toCallerIDMinMatch(number)); 168036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov 1681653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1682653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 16834da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 16844da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=?", mSelectionArgs1); 1685e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 16863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 16883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 16893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 16903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 16913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 16923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 16933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 16943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 16953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 16963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 16973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 16983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 16993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 17003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 17013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 17023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 17033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1704653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1705653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1706653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1707653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1708653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1709653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1710653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1711653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1712653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 17130be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 17140be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 17150be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1716653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1717653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1718653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1719813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1720f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 172114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1722653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1723813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1724813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1725813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 17260be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 1727813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 17280be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 17290be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 17300be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 17310be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 17320be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 17330be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 17340be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 17350be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 17360be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 17370be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 17380be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1739b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 17400be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1741b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 17420be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1743653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1744653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1745653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1746653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1747653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1748653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1749653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1750653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1751653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1752653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1753653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1754653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1755653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1756653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1757653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1758653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1759653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1760653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1761653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1762653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1763653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1764653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1765653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1766653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1767ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId, 1768ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.get(rawContactId)); 1769653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1770653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1771653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1772653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1773653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1774653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1775a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1776a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1777a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1778a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1779a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1780a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1781a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1782a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1783a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1784285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1785285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1786285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1787a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1788a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1789a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1790a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1791813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1792f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1793a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1794813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1795813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1796813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1797813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1798a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1799813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 1800a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1801a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1802a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1803a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1804a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1805a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1806a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1807a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1808a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1809a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1810a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1811ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov /** 1812ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 1813ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1814ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1815ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov public class GroupIdCacheEntry { 1816ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1817ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 1818ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1819ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1820ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1821a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 18223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 1823b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 182431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 18254097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1826f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1827315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1828622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1829622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1830ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1831ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1832ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // is a list of groups with this group id. 1833ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1834ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 1835622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1836f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1837a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1838d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1839a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 184020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 18411129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private CharArrayBuffer mCharArrayBuffer = new CharArrayBuffer(128); 18425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private NameSplitter.Name mName = new NameSplitter.Name(); 184373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 184420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 184509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 184609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 1847ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 184873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1849ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<Long, Account> mInsertedRawContacts = Maps.newHashMap(); 1850b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1851a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private HashSet<Long> mDirtyRawContacts = Sets.newHashSet(); 1852b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1853de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 18541a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 18551a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 185681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 185781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 18584cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 1859d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 186073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 18614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 18624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1863de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1864ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1865ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1866ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1867ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1868ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1869ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1870ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 187135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1872ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 1873de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1874b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1875a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1876b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1877767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper, 1878767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov createPhotoPriorityResolver(context)); 18790e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1880a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1881b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 1882653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 188351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov initForDefaultLocale(); 1884d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1885b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mSetPrimaryStatement = mDb.compileStatement( 1886653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1887653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1888653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1889653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1890653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1891b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mSetSuperPrimaryStatement = mDb.compileStatement( 1892653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1893653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1894653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1895653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1896653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1897653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1898653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1899653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1900653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1901653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1902653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1903b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mRawContactDisplayNameUpdate = mDb.compileStatement( 190425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 19055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov " SET " + 19065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE + "=?," + 19075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY + "=?," + 19085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," + 19095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME + "=?," + 19105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE + "=?," + 19115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY + "=?," + 19125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE + "=?" + 191325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 19143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1915b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mLastStatusUpdate = mDb.compileStatement( 1916a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.CONTACTS + 1917a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1918a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1919a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1920a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1921a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1922a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1923a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1924a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1925a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1926a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 19270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 19280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1929a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " LIMIT 1)" + 1930a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1931e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1932b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mNameLookupInsert = mDb.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1933f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1934f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1935f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1936b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mNameLookupDelete = mDb.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1937f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1938f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1939b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateInsert = mDb.compileStatement( 1940a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1941a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 19420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 19430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 19440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 19450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 19460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 1947a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1948b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateReplace = mDb.compileStatement( 1949a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1950a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 19510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 19520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 19530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 19540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 19550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 19560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1957a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1958b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateAutoTimestamp = mDb.compileStatement( 1959a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 19600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 19610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 1962a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 19630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 19640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 1965b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusAttributionUpdate = mDb.compileStatement( 19660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 19670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 19680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 19690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 19700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1971a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1972b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateDelete = mDb.compileStatement( 1973a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1974a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1975a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1976f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // When setting NAME_VERIFIED to 1 on a raw contact, reset it to 0 1977f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // on all other raw contacts in the same aggregate 1978b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mResetNameVerifiedForOtherRawContacts = mDb.compileStatement( 1979f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 1980f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " SET " + RawContacts.NAME_VERIFIED + "=0" + 1981f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=(" + 1982f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1983f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1984f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?)" + 1985f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " AND " + RawContacts._ID + "!=?"); 1986f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 1987f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1988f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 19891129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdStructuredName = mDbHelper.getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE); 19901129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdOrganization = mDbHelper.getMimeTypeId(Organization.CONTENT_ITEM_TYPE); 19911129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdNickname = mDbHelper.getMimeTypeId(Nickname.CONTENT_ITEM_TYPE); 19921129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdPhone = mDbHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 199304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov 1994bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov verifyAccounts(); 1995bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 199665ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 199765ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov importLegacyContactsAsync(); 199880952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov } else { 199980952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov verifyLocale(); 200065ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov } 200165ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 20022a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov if (isAggregationUpgradeNeeded()) { 20032a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov upgradeAggregationAlgorithm(); 20042a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov } 20052a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 2006b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return (mDb != null); 20074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 20084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2009ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao private void initDataRowHandlers() { 2010ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers = new HashMap<String, DataRowHandler>(); 2011ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao 2012ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 2013ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 2014ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 2015ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 2016ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 2017ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 2018ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 2019ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 2020ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 2021ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao new StructuredNameRowHandler(mNameSplitter)); 2022ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 2023ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao new StructuredPostalRowHandler(mPostalSplitter)); 2024ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 2025ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 2026ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao } 202751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 2028767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov * Visible for testing. 2029767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov */ 2030767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 2031767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov return new PhotoPriorityResolver(context); 2032767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov } 2033767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov 2034767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 203551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 203651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 203704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 20384cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 203904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov mNameSplitter = mDbHelper.createNameSplitter(); 20404cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 20414cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 204251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mCommonNicknameCache = new CommonNicknameCache(mDbHelper.getReadableDatabase()); 2043cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 2044ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao initDataRowHandlers(); 20454cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 20464cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 20474cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao @Override 204851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov public void onConfigurationChanged(Configuration newConfig) { 20494f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL) { 20504f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov return; 20514f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov } 20524f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 205351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov initForDefaultLocale(); 205451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov verifyLocale(); 20554cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 205651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2057c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 2058c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 2059c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 2060c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 2061c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 206251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 206351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 206451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 206551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 206651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 206751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 206851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 206951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void verifyLocale() { 2070f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 2071f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 2072f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 2073f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 2074f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 2075f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 207651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 207751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 207851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 207951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 208051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 208151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 208251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 208351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 208451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 208551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 208651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov AsyncTask<Integer, Void, Void> task = new AsyncTask<Integer, Void, Void>() { 208751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 208851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int savedProviderStatus; 208951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 209051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov @Override 209151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected Void doInBackground(Integer... params) { 209251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov savedProviderStatus = params[0]; 209351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mDbHelper.setLocale(ContactsProvider2.this, currentLocale); 209451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return null; 209551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 209651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 209751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov @Override 209851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void onPostExecute(Void result) { 20999516b6eef76b3504913f5efcadf603969946a3d0Brad Fitzpatrick prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).apply(); 210051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(savedProviderStatus); 2101f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 2102f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // Recursive invocation, needed to cover the case where locale 2103f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // changes once and then changes again before the db upgrade is completed. 2104f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov verifyLocale(); 210551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 210651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov }; 210751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 210851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov task.execute(providerStatus); 210951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 211051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 211131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 2112de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 2113b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 2114b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 211531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 211631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 2117013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 2118013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 2119013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 2120013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 21215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 21225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 21235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 21245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 21255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 21263d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 2127b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 2128b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 21293d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 21303d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2131568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 2132568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 2133568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2134568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2135568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 2136568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 2137568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 2138568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 2139568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 2140bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 2141bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 2142bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (mAccessLatch == null) { 2143bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 2144bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2145568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2146568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 2147568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2148568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 214980952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov final SharedPreferences prefs = 215080952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov PreferenceManager.getDefaultSharedPreferences(getContext()); 215180952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov mDbHelper.setLocale(ContactsProvider2.this, mCurrentLocale); 215280952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 215380952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov 2154bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 2155bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importLegacyContacts(importer)) { 2156bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov onLegacyContactImportSuccess(); 2157bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2158bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov onLegacyContactImportFailure(); 2159568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2160568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2161568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 2162568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2163568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 2164568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2165568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2166bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 2167bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 2168bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 2169bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 2170bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 2171bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 2172bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 2173bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2174b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 2175b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDbHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 2176b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 2177bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 2178bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch.countDown(); 2179bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch = null; 2180bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 2181bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2182bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2183bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 2184bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 2185bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 2186bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 2187bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 2188bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 2189bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 2190bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2191bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 2192bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 2193bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 2194bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 2195bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 2196bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 2197bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 2198bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 2199bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 2200bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2201bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 2202bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2203bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 2204bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 22053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 22063d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 22073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 2208568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 22090e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 22103d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 22113d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 2212bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 2213bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2214bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 2215bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 2216bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 2217bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 22183d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 22193d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 22203d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 2221bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 2222bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 22233d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 22243d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2225a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 2226a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 2227a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 2228a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 2229b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 2230a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 2231a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2232568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 2233568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 2234568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 2235568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 2236568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 2237568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 2238568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 2239568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 2240ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 2241ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 2242ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 2243ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 2244ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 2245ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 2246ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 2247ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 224881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 2249ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2250ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2251568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2252568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2253568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2254568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2255568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 2256568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2257568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 2258568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2259568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2260568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2261568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 2262bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (mAccessLatch != null) { 2263bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 2264bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 2265bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 2266bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 2267bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (match == PROVIDER_STATUS && isLegacyContactImportNeeded()) { 2268bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 2269bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 2270bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov importLegacyContactsAsync(); 2271bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 2272bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2273bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 2274bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2275bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2276bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2277568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2278568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 2279568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2280568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2281568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2282568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 2283568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2284568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 2285568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2286568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2287568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2288568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2289568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 2290568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2291568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 2292568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2293568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 22944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2295285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 2296bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2297b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 2298b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2299285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 23001ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 2301b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2302b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2303b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2304b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 2305285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 2306b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 2307df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 2308a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.clear(); 2309285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2310285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2311285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2312285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 23131129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 2314bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2315b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2316b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2317285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 2318b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 23191ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 23201a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 23211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 2322b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 23231a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 2324b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2325b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2326b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2327bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2328b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2329b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 23301129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 233108e42c9c153a60bf2e7c71dd40bf84bb5fc93555Dmitri Plotnikov for (long rawContactId : mInsertedRawContacts.keySet()) { 2332d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(mDb, rawContactId); 2333d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mContactAggregator.onRawContactInsert(mDb, rawContactId); 2334285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2335b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2336a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov if (!mDirtyRawContacts.isEmpty()) { 2337a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2338a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2339a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mDirtyRawContacts); 2340a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2341a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2342a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2343a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2344b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 2345a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2346a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2347a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mUpdatedRawContacts); 2348a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2349a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2350b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2351b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2352b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 2353b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 23549d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana if (mDbHelper.getSyncState().update(mDb, id, entry.getValue()) <= 0) { 23559d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 23569d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 23579d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 2358b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2359b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2360b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2361b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2362b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2363a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2364a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2365a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2366a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2367a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private void appendIds(StringBuilder sb, HashSet<Long> ids) { 2368b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2369a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2370b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2371a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2372a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2373285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2374285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2375285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2376cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 237781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 237881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 237981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 238081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 238181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 238281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 238381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2384cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2385568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 238651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 238751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mProviderStatus = status; 238851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.ProviderStatus.CONTENT_URI, 238951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov null, false); 239051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 239151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2392285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 2393ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return mInsertedRawContacts.containsKey(rawContactId); 2394285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2395285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 23963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 23973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 23983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 23993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 24003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 24013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 24023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 24033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 24043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 24054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2406de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2407bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 24081129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2409b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2410f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2411f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2412f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2413f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2414a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2415a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 241635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2417a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 241835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2419b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 242035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 242135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2422d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2423d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 24246bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 24256bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 24266bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 24275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2428f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertRawContact(uri, values); 2429f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2430a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2431a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2432a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 24345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2435f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2436f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2437a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2438a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2439a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2440a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2441f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2442f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2443a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2444a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2445a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2446ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2447f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2448f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2449ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2450ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2451ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2452eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 24535aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 245443880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2455eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2456eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2457eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 245882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 245982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 24601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 24611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24621f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2463a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 246481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2465f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2466a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2467a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 24697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 24707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2472de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2473a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2474a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2475a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2476e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2477e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2478e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2479e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2480e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2481e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2482e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2483e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2484e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2485e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2486e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2487e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2488e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 24897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2490e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2491f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2492f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2493e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2494f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2495f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2496f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2497e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2498e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2499e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2500e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2501e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 2502fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2503fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 2504e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2505e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2506e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2507e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2508e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2509e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2510e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2511e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2512e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2513e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2514e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2515e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 2516fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2517fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 2518e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2519e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2520e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2521f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2522f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2523e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2524f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2525f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2526e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2527e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2528f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2529f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2530e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2531f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2532f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2533f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2534f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2535035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2536f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2537e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 25387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2541d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 25426bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 25436bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 25446bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 25456bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2546d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2547de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 25486bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 25496bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 25506bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2551a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2552a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2553f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2554f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2555a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2556a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2557f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertRawContact(Uri uri, ContentValues values) { 2558f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2559f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2560f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2561f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2562e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 25637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25643d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 25653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2566f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 25673d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 25683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2569f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 2570f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 2571f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 2572f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 2573f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2574f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId, aggregationMode); 2575285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2576285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2577e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mInsertedRawContacts.put(rawContactId, account); 2578f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2579023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2580a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2581a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2582a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2583a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2584a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2585a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2586a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2587a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2588f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2589a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2590de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2591de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 259267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2593de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 259420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2595de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2596de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2597de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2598b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2599de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2600de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2601508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2602de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2603de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2604de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2605de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2606de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 26074097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2608b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2609de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2610a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2611a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2612a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2613f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2614de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2615a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2616b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2617a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 26184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 26194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 26208e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 26218e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 26228e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 26238e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 26248e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2625b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2626f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 26278e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 26288e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 26298e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 26308e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 263169cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode, false); 2632f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 26338e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 26348e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 26358e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2636b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2637f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 26388e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 26398e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 26408e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2641f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 26428e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2643f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2644c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 26452a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId); 2646f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 26478e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2648f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2649f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2650f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2651a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 26525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 26539261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 26549261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 26555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 26569261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 26579261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 26589261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 26599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 26609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 2661ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId, 2662ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Account account) { 2663ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2664ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (account == null) { 26654da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 2666ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 26674da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov RawContacts._ID + "=?", mSelectionArgs1, null, null, null); 2668ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov try { 2669ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2670ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = c.getString(RawContactsQuery.ACCOUNT_NAME); 2671ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = c.getString(RawContactsQuery.ACCOUNT_TYPE); 2672ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 2673ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov account = new Account(accountName, accountType); 2674ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 26759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2676ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } finally { 2677ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov c.close(); 26789261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 26799261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2680ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 26819261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 26829261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 2683ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov + "has a sourceid the the contact must be associated with " 26849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 26859261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 26869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2687ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ArrayList<GroupIdCacheEntry> entries = mGroupIdCache.get(sourceId); 2688ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entries == null) { 2689ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries = new ArrayList<GroupIdCacheEntry>(1); 2690ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.put(sourceId, entries); 2691ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2692ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2693ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int count = entries.size(); 2694ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov for (int i = 0; i < count; i++) { 2695ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = entries.get(i); 2696ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entry.accountName.equals(account.name) && entry.accountType.equals(account.type)) { 2697ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 2698ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2699ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2700ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2701ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = new GroupIdCacheEntry(); 2702ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountName = account.name; 2703ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountType = account.type; 2704ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.sourceId = sourceId; 2705ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries.add(0, entry); 2706ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 27079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 27085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 2709ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 27109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2711df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 27129261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 2713ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2714ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = c.getLong(0); 27159261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 27169261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2717df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2718df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 27199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 27209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 27219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 27229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 27239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 27249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2725ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = groupId; 27269261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 27279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 27289261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 27299261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2730ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2731ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 27329261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 27339261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2734d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private interface DisplayNameQuery { 27351129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov public static final String RAW_SQL = 27361129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov "SELECT " 27371129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + DataColumns.MIMETYPE_ID + "," 27381129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.IS_PRIMARY + "," 27391129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.DATA1 + "," 27405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA2 + "," 27415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA3 + "," 27425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA4 + "," 27435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA5 + "," 27445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA6 + "," 27455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA7 + "," 27465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA8 + "," 27475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA9 + "," 27485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA10 + "," 27495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA11 + 27501129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " FROM " + Tables.DATA + 27511129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " WHERE " + Data.RAW_CONTACT_ID + "=?" + 27521129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " AND (" + Data.DATA1 + " NOT NULL OR " + 27531129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Organization.TITLE + " NOT NULL)"; 2754d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2755d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int MIMETYPE = 0; 2756d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int IS_PRIMARY = 1; 27575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int DATA1 = 2; 27585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int GIVEN_NAME = 3; // data2 27595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FAMILY_NAME = 4; // data3 27605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PREFIX = 5; // data4 27615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int TITLE = 5; // data4 27625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int MIDDLE_NAME = 6; // data5 27635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int SUFFIX = 7; // data6 27645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_GIVEN_NAME = 8; // data7 27655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_MIDDLE_NAME = 9; // data8 27665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME = 9; // data8 27675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_FAMILY_NAME = 10; // data9 27685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FULL_NAME_STYLE = 11; // data10 27695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME_STYLE = 11; // data10 27705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_NAME_STYLE = 12; // data11 2771d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2772d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2773d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov /** 2774d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * Updates a raw contact display name based on data rows, e.g. structured name, 2775d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * organization, email etc. 2776d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov */ 2777ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 2778bca1c8b44f99528fc123d5547723e44771e8e934Mike Lockwood int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 27795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name bestName = null; 27805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestDisplayName = null; 27815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestPhoneticName = null; 27825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 2783d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 27841129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 27851129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Cursor c = db.rawQuery(DisplayNameQuery.RAW_SQL, mSelectionArgs1); 2786d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov try { 2787d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov while (c.moveToNext()) { 27881129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov int mimeType = c.getInt(DisplayNameQuery.MIMETYPE); 27895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int source = getDisplayNameSource(mimeType); 27905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source < bestDisplayNameSource || source == DisplayNameSources.UNDEFINED) { 27915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 27925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 27931129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 27945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source == bestDisplayNameSource && c.getInt(DisplayNameQuery.IS_PRIMARY) == 0) { 27955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 2796d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 27971129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 27985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mimeType == mMimeTypeIdStructuredName) { 27995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name name; 28005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestName != null) { 28015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = new NameSplitter.Name(); 28025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 28035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = mName; 28045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.clear(); 28055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.prefix = c.getString(DisplayNameQuery.PREFIX); 28075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.givenNames = c.getString(DisplayNameQuery.GIVEN_NAME); 28085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.middleName = c.getString(DisplayNameQuery.MIDDLE_NAME); 28095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.familyName = c.getString(DisplayNameQuery.FAMILY_NAME); 28105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.suffix = c.getString(DisplayNameQuery.SUFFIX); 28115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.fullNameStyle = c.isNull(DisplayNameQuery.FULL_NAME_STYLE) 28125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? FullNameStyle.UNDEFINED 28135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.FULL_NAME_STYLE); 28145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticFamilyName = c.getString(DisplayNameQuery.PHONETIC_FAMILY_NAME); 28155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticMiddleName = c.getString(DisplayNameQuery.PHONETIC_MIDDLE_NAME); 28165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticGivenName = c.getString(DisplayNameQuery.PHONETIC_GIVEN_NAME); 28175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticNameStyle = c.isNull(DisplayNameQuery.PHONETIC_NAME_STYLE) 28185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 28195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.PHONETIC_NAME_STYLE); 28205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (!name.isEmpty()) { 28215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 28225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName = name; 28235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else if (mimeType == mMimeTypeIdOrganization) { 28255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 28265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 28275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 2828d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov bestDisplayNameSource = source; 28291129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 28301129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 28315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = c.getString(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME); 28325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = 28335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.isNull(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE) 28345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 28355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE); 28365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 28375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.TITLE, mCharArrayBuffer); 28385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 28391129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayNameSource = source; 28401129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 28411129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 28425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 28435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 28441129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 2845d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 28465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 28475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Display name is at DATA1 in all other types. 28485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // This is ensured in the constructor. 28495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 28515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 28525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 28535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 28545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 28555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 28565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 28575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 28585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 2859d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2860d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2861d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2862d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } finally { 2863d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov c.close(); 2864d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2865d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 28665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary; 28675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNameAlternative; 28685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyPrimary = null; 28695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyAlternative = null; 28705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int displayNameStyle = FullNameStyle.UNDEFINED; 28715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestDisplayNameSource == DisplayNameSources.STRUCTURED_NAME) { 28735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = bestName.fullNameStyle; 28745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.CJK 28755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.UNDEFINED) { 28765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 28775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName.fullNameStyle = displayNameStyle; 28785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = mNameSplitter.join(bestName, true); 28815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative = mNameSplitter.join(bestName, false); 28825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = mNameSplitter.joinPhoneticName(bestName); 28845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = bestName.phoneticNameStyle; 28855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 28865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = displayNameAlternative = bestDisplayName; 28875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 28895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticName != null) { 28905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = bestPhoneticName; 28915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticNameStyle == PhoneticNameStyle.UNDEFINED) { 28925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = mNameSplitter.guessPhoneticNameStyle(bestPhoneticName); 28935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 28955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED) { 28965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.guessFullNameStyle(bestDisplayName); 28975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED 28985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.CJK) { 28995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedNameStyleBasedOnPhoneticNameStyle( 29005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle, bestPhoneticNameStyle); 29015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 29035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 2904ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao if (displayNameStyle == FullNameStyle.CHINESE || 2905ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao displayNameStyle == FullNameStyle.CJK) { 29065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = 2907cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().getSortKey( 2908ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao displayNamePrimary, displayNameStyle); 29095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (sortKeyPrimary == null) { 29135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = displayNamePrimary; 29145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyAlternative = displayNameAlternative; 29155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov setDisplayName(rawContactId, bestDisplayNameSource, displayNamePrimary, 29185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative, bestPhoneticName, bestPhoneticNameStyle, 29195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary, sortKeyAlternative); 2920d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2921d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 29221129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private int getDisplayNameSource(int mimeTypeId) { 29231129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (mimeTypeId == mMimeTypeIdStructuredName) { 29241129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.STRUCTURED_NAME; 29251129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdEmail) { 29261129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.EMAIL; 29271129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdPhone) { 29281129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.PHONE; 29291129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdOrganization) { 29301129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.ORGANIZATION; 29311129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdNickname) { 29321129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.NICKNAME; 29331129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else { 29341129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.UNDEFINED; 29351129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 29361129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 29371129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 29389261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 293920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 294020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2941f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 294220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 294320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2944de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2945de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 294614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2947de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2948de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 294914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 295014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2951a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2952a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 2953f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 295488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 295588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 295620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 295720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2958de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 295920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 296020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 296120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 296220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 296320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 296488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 296588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 296688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 296720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2968f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 296988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 297088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 29714da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 29724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=?", 29734da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 2974f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 297520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 297620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 297720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 297820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 297920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 298014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 298120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 298220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 298320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 298420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 298520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 298620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 298720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 298820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 298920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 29907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 299120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 299220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 299320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2994a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2995813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return rowHandler.delete(mDb, c); 299620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 299720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 299820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 299920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 300020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 300120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 3002ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 3003ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 3004f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 3005f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 3006f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 3007f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 3008e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 3009ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3010ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 3011f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 301267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 3013f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 301467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 3015f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 3016ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3017f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 3018f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 301973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 302073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3021f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 3022ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3023f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 30241a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3025ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 3026ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3027ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 3028ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3029ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 30305aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 3031e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 30325aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 30331a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 30341a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3035e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 30361a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 3037e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 3038e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3039e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3040ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 304182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 30421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 304382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 304482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 30450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 30464dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 30474dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 30480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 304982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 30504dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 30514dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 30524dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 30534dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 30541f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 30551f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3056dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 3057dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 305882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 3059f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 30602526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 3061dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 3062dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 3063dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 30642526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 30652526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 30661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 3067dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 3068dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 30690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 30700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 30710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 30720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3073dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 3074dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 3075dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 30762526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov String mimeTypeIdIm = String.valueOf(mMimeTypeIdIm); 3077dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 30782526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov String mimeTypeIdEmail = String.valueOf(mMimeTypeIdEmail); 3079f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3080f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 3081f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 3082f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 3083f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3084f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 3085f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 30862526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 30872526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 30882526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 30892526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 30902526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 30912526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 30922526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 30932526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 3094dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 30952526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 30962526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3097dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 30982526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 30992526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 3100dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 31012526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 31022526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 31032526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 31042526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 31052526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 31062526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 3107dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 31082526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 31092526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3110dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 3111dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 31121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 311382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 31142526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 31152526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 3116dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 311770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 3118f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 311970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 31201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 31211f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 3122de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 31232526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 3124c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 31251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 312667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 31275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 3128e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 31291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 31301f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 31311f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 31321f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 313431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 313531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 313631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 31371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31381f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 313982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 3140a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 3141a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 3142a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 3143a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 3144a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3145a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3146a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 314782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 3148a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 3149a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 315082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 315182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 315282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 315382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 315482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 3155a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 315682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 315782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 3158aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori mValues.put(StatusUpdates.CHAT_CAPABILITY, 3159aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori values.getAsString(StatusUpdates.CHAT_CAPABILITY)); 31601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3161a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 3162a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 3163a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3164e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 31650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 316682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 316782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 31680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 31690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 31700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 31710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 31720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 31730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 31740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 31750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 31760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 31770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 31780a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 31790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3180a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 3181a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 3182a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 318382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 318482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 3185a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 3186a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 31875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 3, status); 31885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 4, resPackage); 31895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 5, iconResource); 31905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 6, labelResource); 3191a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 3192a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 3193a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3194a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 3195a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 31965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 2, status); 31975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 3, resPackage); 31985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 4, iconResource); 31995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 5, labelResource); 3200a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 3201a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 3202a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 32030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 3204a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 32055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 2, status); 3206a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 32075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 4, status); 3208a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 32090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 32105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusAttributionUpdate, 1, resPackage); 32115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 2, iconResource); 32125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 3, labelResource); 32130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 32140a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 3215a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3216e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3217e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3218bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3219a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 3220a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 3221a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 3222a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 3223a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3224a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3225a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 32261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32271f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 32284f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3229de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 3230bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3231b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 3232b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3233b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3234f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3235f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 3236508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 3237508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 323835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3239b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 324035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3241b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 3242b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3243b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3244b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3245b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 3246b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3247cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 3248cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 3249cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 3250cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3251cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3252d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3253d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3254cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return deleteContact(contactId); 32556bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 32566bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 32579fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 32582e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 32592e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 32602e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3261fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3262fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 32632e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 32642e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 32652e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 32662e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return deleteContact(contactId); 32672e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 32682e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 32699fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 32709fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 32719fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann long contactId = ContentUris.parseId(uri); 32729fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 32739fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 32749fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 32759fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 32769fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 32779fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 32789fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 32799fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 32809fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 32819fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 32829fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 32839fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 328460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 32859fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 32869fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 32879fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann Cursor c = query(db, lookupQb, null, selection, args, null, null, null); 32889fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 32899fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 32909fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 32919fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return deleteContact(contactId); 32929fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 32939fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 32949fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 32959fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 32969fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 32979fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 32989fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 32999fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 33009fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 33019fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 33022971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 33032971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 3304fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, 3305fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 3306e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 33072971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 33082971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 33092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 3310fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 3311fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 3312fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 33132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 33142971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 33152971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 33162971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 33172971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 33182971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 33192971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 33205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 33212971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 3322fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return deleteRawContact(rawContactId, mDbHelper.getContactId(rawContactId), 3323fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 3324508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3325508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 332620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3327f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 3328944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 3329f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 333020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 333120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 333248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 333348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 333448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 333548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3336508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3337f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 33384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 33394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 3340ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3341ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3342ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3343f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 33445aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 33452971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 33462971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 33472971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 33482971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 33492971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 3350e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 33512971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 33522971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 33535aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 33542971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 33552971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 33562971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 33572971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 335881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3359f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 336081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 33612971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3362508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3363508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3364eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 336543880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3366e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3367eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3368eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 336982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 33700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 33711f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 33721f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 337381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 337481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 33753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 337681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3377508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 33784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 33794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 33801c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3381ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3382b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 338394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 3384de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 338594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 338694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 338794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 338894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3389f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 3390de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 339194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 339294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 339394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3394f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 3395de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 339694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 339794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 33981a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 339994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 340094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 340194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 34025aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 3403e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 34041a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3405e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3406e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3407e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3408cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int deleteContact(long contactId) { 340996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 3410cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 341196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 341296b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 3413cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3414cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3415cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3416cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov markRawContactAsDeleted(rawContactId); 3417cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3418cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3419cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3420cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3421cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3422cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3423cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3424cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3425fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 34263389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3427f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 342814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 3429fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov int count = mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 3430fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForContact(mDb, contactId); 3431fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 343233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 3433b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 3434cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return markRawContactAsDeleted(rawContactId); 343533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 343633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 343733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 34380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 34399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 34409705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 34419705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 34429705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 34439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 34449705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 34459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 34469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 34470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 34480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3449cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 345081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 345181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3452cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3453cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3454cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3455cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3456cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3457cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3458cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return updateRawContact(rawContactId, mValues); 3459cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3460cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 34614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3462de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3463de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3464bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3465b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3466b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3467b5a4add17815167d20a90645779df34cdf45280dFred Quintana 346835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 346900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 347000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3471b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3472b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 34731129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 3474b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 3475b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3476b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3477b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3478f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3479f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 348000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 348135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3482b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3483b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3484b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3485b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3486b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3487b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3488b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3489b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3490b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3491b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3492b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 349335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3494d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 34958c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 349600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 349700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 349800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3499d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 35008c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 3501c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3502c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3503c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 35042e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 35052e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 35062e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 35072e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 35082e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3509fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3510fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 35112e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 35122e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 35132e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 35148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count = updateContactOptions(contactId, values); 35152e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 35162e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 35172e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 35187d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 35197d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 35207d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 35217d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 35227d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 35237d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 35247d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 35257d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 35267d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 35277d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 352820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3529944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3530f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 353181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3532f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 353381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 353420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 353520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3536c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 353748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 353848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 353948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 354048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3541f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 354281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3543f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 354481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 354500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 354600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 35477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 35485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 35495ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 35504529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 35517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 35527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 35537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 35545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 355533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 35564529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 35574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 35584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 35594529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 35604529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 35614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 35624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1); 35634529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 35647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 35657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 35667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3567ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 35685aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3569f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 357081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3571f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 357281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3573ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3574ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3575ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3576ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3577ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 35784da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 35794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 358073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 35815aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 35825aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 358381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3584f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 358581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3586ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3587ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3588ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3589127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 3590de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 3591b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3592b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3593b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3594eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3595e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3596e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 359743880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3598eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3599eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3600eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 36019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 36029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 36039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 36049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 360681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 360781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 3608f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 360981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 361000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 361100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 361200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 36134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 36169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 36179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 36189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 36199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 36209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 36219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 36229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 36239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 36249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 36259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 36269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 36289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 36299705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 36309705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 36319705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 36329705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 36339705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36349705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 36359705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 36369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 36379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 36399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 36409705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 36419705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 36429705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 36439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 36449705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 36459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 36469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 36479705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 36489705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36499705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 36509705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 36519705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 36529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 36539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 36549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 36559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 36569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 36579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 36589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 36599705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 36609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 36619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 36629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 36639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 36659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 36669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 36679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 36689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 3669aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.CHAT_CAPABILITY, values, 3670aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori StatusUpdates.CHAT_CAPABILITY); 36719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 36729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 36745aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 3675f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 367673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3677ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3678ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 367973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 3680f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 368173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 368273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 368373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 368473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 368573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 368673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 368773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 368873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3689ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 36901a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 36911a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 369294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 36936ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 36941129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 36956ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 3696e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 36976ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 36986ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 36996ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 37006ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 37016ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 37026ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 37036ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 37046ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 37056ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 3706ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 37076ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 37086ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 37096ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 37106ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 37116ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 37126ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 37136ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 37146ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 371594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 371694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 371794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 3718b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 3719b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 3720e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 37211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 37221a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3723e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3724e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3725e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3726e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 37274529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 37284529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 37294529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 37304529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 37314529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 373273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 37334529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3734b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 373551bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 37364529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 37374529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 37384529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 37394529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 37404529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov updateRawContact(rawContactId, values); 37414529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 37424529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 37434529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 37444529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 37454529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 37464529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 37474529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 37484529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 37494529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 37504529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values) { 375196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 375296b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 375319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 375419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 375519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 3756ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 3757ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 375819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 375919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 376096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1, null, null, null); 376119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 376219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 376319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 3764ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 3765ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 376619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 376719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 376819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 376919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 377019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 377119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 377219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 3773f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 377496b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker int count = mDb.update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 37755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3776f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 3777f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 3778f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 3779f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 3780f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 3781f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 378269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode, false); 3783f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 3784f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 3785433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 37864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3787433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3788285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 37892b7a632bba423357ae5641f94da6a2f71afc523bDmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(mDb, rawContactId); 3790285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 3791f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 3792f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 3793f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 3794f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 3795f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 3796f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(1, rawContactId); 3797f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(2, rawContactId); 3798f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.execute(); 3799f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 3800f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(mDb, rawContactId); 3801f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 380219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 380319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 3804ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.put(rawContactId, new Account(accountName, accountType)); 380519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 38065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 380833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 380933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3810321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3811f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 381220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 381320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 381420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 38155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 381620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 381720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 381820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 381920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 382020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3821b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 382220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 382320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 382470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 382570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 382620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 382720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 382820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 382970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 383020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 383170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 383220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 383370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 383420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 383570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 383620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 383720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3838653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 383920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3840653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3841653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 384214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 3843653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 3844653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 3845f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 384620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3847653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 3848653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 384920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 385020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3851653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 385220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 385320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3854f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 3855653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 3856653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 3857321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3858653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 385914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 3860a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3861813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (rowHandler.update(mDb, values, c, callerIsSyncAdapter)) { 3862813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 1; 3863813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } else { 3864813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 0; 3865a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 3866321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3867321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 38688c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 38698c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov String[] selectionArgs) { 38708c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 3871b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 38728c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 38738c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 38748c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 38758c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 38768c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 38778c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov updateContactOptions(contactId, values); 38788c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 38798c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 38808c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 38818c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 38828c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 38838c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 38848c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 38858c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 38868c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 38878c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 3888d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 38898c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3890b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3891d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3892b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 3893d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3894b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 3895d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3896b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3897d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3898b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3899d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 3900d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3901d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 39028c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 3903d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 3904d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3905d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 39068c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 3907c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 39088c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3909c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 3910c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 39114da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 39124da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?", mSelectionArgs1); 39138c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 39148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 39158c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 39168c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3917b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 39188c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3919b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 39208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3921b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 39228c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3923b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 39248c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3925b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 39268c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 39278c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 39289b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori int rslt = mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 39296e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 39309b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 39319b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 39329b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 39339b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 39349b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 39359b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 3936f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3937d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3938127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 3939127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 39400c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 39410c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 394280c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 39430c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 39440c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 39450c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 39460c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 39470c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 39480c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 39490c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 3950b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3951127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 39520c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 39534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 39544da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 39550c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 39564da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 39574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 39580c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 39596bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 39606bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 39610c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 39620c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 39630c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 39640c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 3965127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 3966127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 39673389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 396869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1, 396969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 397069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2, 397169cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 3972dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 39732a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1); 39742a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2); 3975127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3976127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 3977127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 3978127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3979b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3980b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3981f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao /** 3982f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao * Check whether GOOGLE_MY_CONTACTS_GROUP exists, otherwise create it. 3983f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao * 3984f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao * @return the group id 3985f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao */ 3986f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao private long getOrCreateMyContactsGroupInTransaction(String accountName, String accountType) { 3987f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao Cursor cursor = mDb.query(Tables.GROUPS, new String[] {"_id"}, 3988f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao Groups.ACCOUNT_NAME + " =? AND " + Groups.ACCOUNT_TYPE + " =? AND " 3989f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao + Groups.TITLE + " =?", 3990f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao new String[] {accountName, accountType, GOOGLE_MY_CONTACTS_GROUP_TITLE}, 3991f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao null, null, null); 3992f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao try { 3993f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao if(cursor.moveToNext()) { 3994f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao return cursor.getLong(0); 3995f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao } 3996f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao } finally { 3997f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao cursor.close(); 3998f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao } 3999f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao 4000f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao ContentValues values = new ContentValues(); 4001f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao values.put(Groups.TITLE, GOOGLE_MY_CONTACTS_GROUP_TITLE); 4002f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao values.put(Groups.ACCOUNT_NAME, accountName); 4003f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao values.put(Groups.ACCOUNT_TYPE, accountType); 4004f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao values.put(Groups.GROUP_VISIBLE, "1"); 4005f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao return mDb.insert(Tables.GROUPS, null, values); 4006f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao } 4007f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao 400870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 4009f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 4010627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 4011627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov boolean hasUnassignedContacts[] = new boolean[]{false}; 401270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 401370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 4014743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts); 4015743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 4016743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // Add a row to the ACCOUNTS table for each new account 4017743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 4018743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov if (!existingAccounts.contains(account)) { 4019743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 4020743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov + ", " + RawContacts.ACCOUNT_TYPE + ") VALUES (?, ?)", 4021743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov new String[] {account.name, account.type}); 4022743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 4023743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 402448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 4025627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 4026743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // in the accountsToDelete set will be extra accounts whose data must be deleted. 4027627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 4028627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 4029627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 403070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 403170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 403270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 40335f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 4034627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 4035627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4036627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 4037627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 4038627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 4039627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4040627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 4041627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 4042627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "SELECT " + RawContacts._ID + 4043627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4044627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4045627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 4046627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4047627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 4048627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4049627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 4050627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4051627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 4052627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 4053627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 4054743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL( 4055743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 4056743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 4057743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + "=?", params); 4058627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4059627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 406033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov if (!accountsToDelete.isEmpty()) { 406133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 406233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 406333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // names of photos. If so, fix up those contacts. 406433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 406533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Cursor cursor = mDb.rawQuery("SELECT " + Contacts._ID + 406633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 406733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 406869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 406969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 407069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 407133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 407233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 407369cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 407469cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 407533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 407633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 407733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 407833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 407933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 408033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 408133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 408233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 408333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 408433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 408533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 408633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 408733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 4088627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (hasUnassignedContacts[0]) { 4089627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4090627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Account primaryAccount = null; 4091627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 409273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (isWritableAccount(account.type)) { 4093627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov primaryAccount = account; 4094627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov break; 4095627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4096627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4097627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4098627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (primaryAccount != null) { 4099627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {primaryAccount.name, primaryAccount.type}; 4100f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao if (primaryAccount.type.equals(DEFAULT_ACCOUNT_TYPE)) { 4101f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao long groupId = getOrCreateMyContactsGroupInTransaction( 4102f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao primaryAccount.name, primaryAccount.type); 4103f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao if (groupId != -1) { 4104f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao long mimeTypeId = mDbHelper.getMimeTypeId( 4105f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao GroupMembership.CONTENT_ITEM_TYPE); 4106f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao mDb.execSQL( 4107f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao "INSERT INTO " + Tables.DATA + "(" + DataColumns.MIMETYPE_ID + 4108f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao ", " + Data.RAW_CONTACT_ID + ", " 4109f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao + GroupMembership.GROUP_ROW_ID + ") " + 41106dddb9abd6f738e43b41a4687c318533085ff0c7Dmitri Plotnikov "SELECT " + mimeTypeId + ", " 41116dddb9abd6f738e43b41a4687c318533085ff0c7Dmitri Plotnikov + RawContacts._ID + ", " + groupId + 4112f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao " FROM " + Tables.RAW_CONTACTS + 4113f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + 41146dddb9abd6f738e43b41a4687c318533085ff0c7Dmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL" 4115f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao ); 4116f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao } 4117f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao } 4118627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4119627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 4120627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + RawContacts.ACCOUNT_NAME + "=?," 4121627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=?" + 4122627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + 4123627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL", params); 4124627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4125627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // We don't currently support groups for unsynced accounts, so this is for 4126627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // the future 4127627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4128627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "UPDATE " + Tables.GROUPS + 4129627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " SET " + Groups.ACCOUNT_NAME + "=?," 4130627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + Groups.ACCOUNT_TYPE + "=?" + 4131627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " IS NULL" + 4132627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " IS NULL", params); 4133743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 4134743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL( 4135743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 4136743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + 4137743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL"); 4138627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 413970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4140627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4141609cc5b4c96a6981f675a70ff743ecfec2b448e6Daniel Lehmann mDbHelper.updateAllVisible(); 4142609cc5b4c96a6981f675a70ff743ecfec2b448e6Daniel Lehmann 4143b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 414470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 414570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 414670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 414770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 414873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 414970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4150619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4151619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 4152627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 4153627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 4154743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov private void findValidAccounts(Set<Account> validAccounts, boolean[] hasUnassignedContacts) { 4155743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov Cursor c = mDb.rawQuery( 4156743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "SELECT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 4157743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " FROM " + Tables.ACCOUNTS, null); 4158627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4159627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 4160627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (c.isNull(0) && c.isNull(1)) { 4161627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov hasUnassignedContacts[0] = true; 4162627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } else { 4163627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 4164627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4165627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4166627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 4167627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 4168627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4169627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4170627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4171627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov /** 4172622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 4173622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 417467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 417567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 417667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 417767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 417867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 417967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 418067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 418167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 418267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 418367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 418467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 418567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 4186dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 4187622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 4188dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 4189dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 4190622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4191622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4192dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 4193622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4194622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 41954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 41964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 41974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 4198bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 4199bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 4200bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 42010b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 4202b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 420335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4204d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 42051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 4206c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 4207c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4208619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 4209619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 4210a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 42114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 421235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 4213b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 421435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 421535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4216d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 4217763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4218619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 4219619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4220619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4221d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 42224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 4223763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 42244da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 42254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 42266bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 42276bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 42286bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 42295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 42305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 42315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 42325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 42335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 4234fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4235fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 42365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 42385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 42392d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill // TODO: pull this out into a method and generalize to not require contactId 42405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 42415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4242763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 42434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String[] args; 42444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (selectionArgs == null) { 42454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[2]; 42464da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } else { 42474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[selectionArgs.length + 2]; 42484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 42494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 42504da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args[0] = String.valueOf(contactId); 425160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 42524da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 42534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 42545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 42555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 42565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 42575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 42605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4262763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 42634da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 42644da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 42654da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 42665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 42675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4269f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 4270f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 427142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 4272763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 4273f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 42744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 42754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 42764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 4277f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 4278f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 4279f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 428042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 428142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 428242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 428342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return db.rawQuery( 428442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 428542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 428642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 428742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 428842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 428942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 4290ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 4291916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 4292ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 4293916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 4294ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4295916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet(qb, uri, projection, filterParam); 4296ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4297ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4298ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4299ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 4300ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 43014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 4302ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 4303d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 43044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 43054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4306e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 43075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 43084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 43094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 43104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4311763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4312ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 43135e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 43145e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 43155e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 43165e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar starredProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 43175e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar frequentProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 43185e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 43195e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 43204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 43214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 43224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 4323d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 43245e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 43255e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 43264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 4327d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4328d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 4329d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 4330763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 43314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 43324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 4333d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 43345e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 43355e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 4336d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 4337d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 43384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 4339d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4340d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 4341d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 4342d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 43434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 43444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 4345d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 4346d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 4347d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4348d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 4349d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4350d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4351ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 4352763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4353b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 435471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 43554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 4356b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4357b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 4358b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4359b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 4360d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 43614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 436282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 43634da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 43644da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 43656bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 43666bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 436700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 4368ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 43693653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 437082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 43714da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 43724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 43733653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 43743653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 43753653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 43763653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 43774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 437882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 437989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 43802815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 43812815f58f72f109790585931f601a63ddc02536a5Evan Millar } 43822815f58f72f109790585931f601a63ddc02536a5Evan Millar 438348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 438482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 43854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 438648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 43874da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 438848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 438948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 439048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 4391ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 439282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 439389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 4394ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 43954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 43964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4397a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 43985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 439945d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 44005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 44015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 44025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 44035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 44047318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 44055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 440645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 44075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 44095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 44105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 44115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 44125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 44145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 44155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 44165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 44175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 44185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 44195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 44205e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 442145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 442245d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 442345d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 442445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 442545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 442645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 442745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 44285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4430a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 4431ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 44325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 4433a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4434a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4435a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 4436ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4437ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4438ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 44394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 444082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 444189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 44424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 44434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 44444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 444548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 444682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 44474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 44484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 44494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 445048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 445148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 445248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 44535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 445482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 445589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 44564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 445708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 445808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String address = mDbHelper.extractAddressFromEmailAddress(email); 445908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 446008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 44614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 4462ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4463ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4464ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 44655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 446682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 446707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 446807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 446907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 447007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 447107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 447207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 447307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 44745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 447507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 447607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 447707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 447807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 447907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 448007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 448107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 448207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 448307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 448407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 448507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.DATA1 + " LIKE "); 448607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 448720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 448820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 448920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 449007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 449107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov /* 449207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * Using a UNION instead of an "OR" to make SQLite use the right 449307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * indexes. We need it to use the (mimetype,data1) index for the 449407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * email lookup (see above), but not for the name lookup. 449507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * SQLite is not smart enough to use the index on one side of an OR 449607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * but not on the other. Using two separate nested queries 449707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * and a UNION between them does the job. 449807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov */ 449907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 450007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " UNION SELECT " + Data._ID + 450107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 450207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 450307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN "); 45047318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 450520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 45065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4508a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 45095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 4511a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4512a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4513a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 45145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 45155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 4517ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 451882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 451989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 452089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 4521ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4522ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4523ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 452448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 452582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 45264da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 452748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 452848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 45294da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 453048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 453148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 453248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 45335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 4534763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 45354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 45364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 45374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 45385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 45395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 4540763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 45414da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 45424da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 45434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 45444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 45454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 45465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 45475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 454882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 45494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 45504da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 4551e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4552e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4553e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 4554e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 455582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 4556e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4557e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4558e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 45594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 456082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 45614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 45624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 4563a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 4564a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 4565a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 4566a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 45674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4568a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 4569a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 4570a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 4571e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 4572a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4573a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4574e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 4575b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 4576e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 4577e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 4578e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 4579e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 4580e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 4581a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 4582a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4583a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4584ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 4585b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4586ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 458789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4588ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4589ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4590ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4591ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 4592b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4593ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 45944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 45954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 4596ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4597ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4598ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4599ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 4600b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 4601ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 460289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 460389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 4604ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4605ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4606ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4607b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 46080c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 4609b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 4610b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 4611b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4612b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 461331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 4614d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 46152d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 46162d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 46172d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 46182d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 461931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 4620d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 4621d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 462231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 462331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 462431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 462531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4626763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 46277581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 46287581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 46292d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 463031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 463131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4632eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 4633eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 4634eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 463589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4636e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4637e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 4638e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 4639b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 4640e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 464182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4642b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 4643e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4644e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 464582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4646b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 4647e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4648e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4649e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4650eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 4651eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 4652eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 465382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 46540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 46555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 46565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 46575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 465882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 46590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 46604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 46614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 46625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 46635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 46645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 4665c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 4666a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 4667c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4668c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4669c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 46702d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 46712d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill return mGlobalSearchSupport.handleSearchShortcutRefresh(db, lookupKey, projection); 4672c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4673c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 46741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 4675b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 46761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 46771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 46781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 46791b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 4680b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 46811b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 46821b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 46831b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 46841b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 46851b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 4686b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 46871b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 46881b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 46891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 46901b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 46911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 4692b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 46931b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 469471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 46951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 46961b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 46971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 469846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 469946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 470046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 470146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 470246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 470346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 470446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 470546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 47064da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 47074da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 470846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 470946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 471046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 471109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 471209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 471309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 471409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 47154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 4716f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 4717c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 47184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 47207f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov qb.setStrictProjectionMap(true); 47217f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 4722ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 4723ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 4724ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 4725ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov cursor = bundleLetterCountExtras(cursor, db, qb, selection, selectionArgs, sortOrder); 4726ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4727ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 47285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 47295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 47305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 47315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 47325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 4733038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 4734038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 4735038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 4736038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 47375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 47385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 47394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 47404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 47414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 47434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 474509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 474609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 474709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 474809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 474909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 475009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 475109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 475209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 475309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 475409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 475509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 475609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 475709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 475809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 475909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 476009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 476109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 4762bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 4763bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 4764bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 4765bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 4766ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4767bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 4768bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 4769ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 4770ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4771bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 4772bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 4773bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 4774bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4775de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 4776ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4777ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4778ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 4779ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 4780ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 4781ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 4782ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 4783ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder) { 4784ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 4785ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4786ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 4787ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 4788ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 4789ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 4790ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 4791ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 4792ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 4793ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 4794ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 4795ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 4796ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 4797ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4798ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 4799ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 4800ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4801ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4802bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 4803ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 4804bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 4805bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "SUBSTR(" + sortKey + ",1,1) AS " + AddressBookIndexQuery.LETTER); 4806bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4807bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 4808bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 4809bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 4810bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 4811bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 4812bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 4813bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 4814ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 4815bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "GET_PHONEBOOK_INDEX(SUBSTR(" + sortKey + ",1,1),'" + locale + "')" 4816bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 4817ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 4818ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov "COUNT(" + Contacts._ID + ") AS " + AddressBookIndexQuery.COUNT); 4819ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 4820ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4821f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 4822ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 4823ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 4824ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4825ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 4826f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 4827ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 4828ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 4829bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 4830bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 4831bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4832bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 4833bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 4834bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 4835ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 4836f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 4837bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 4838bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 4839bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 4840bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 4841bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 4842bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 4843bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 4844bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 4845bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4846bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4847bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4848bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 4849bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 4850bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 4851bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 4852bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4853bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 4854bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 4855bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 4856ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4857ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4858ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov final Bundle bundle = new Bundle(); 4859ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 4860f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 4861ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return new CursorWrapper(cursor) { 4862ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4863ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov @Override 4864ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov public Bundle getExtras() { 4865ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return bundle; 4866ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4867ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 4868ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 4869f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 4870ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4871ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4872ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 48732d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 487492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 487592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 487692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 487792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 48782d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 48792d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 48805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 48815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 48825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 488392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 488492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 488592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 488692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 488792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 488892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 488992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 489092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 489192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 489292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 489392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 489492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 489592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 489692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 489792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 489892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 489992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 490092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 490192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 49025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 49035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 49065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 49095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 49105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 49125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 49135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 49145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 49155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 49165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 49175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 49195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 49205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 49215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 49225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 49255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 49265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 49275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 49285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 49295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 493092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 49315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 49325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 49335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 49365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 49375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 49395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 49405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 49415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 49425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 49435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 49445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 49455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 49465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 49475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 49485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 494992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 495092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 49515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 49525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 49535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 49545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 49585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 49595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 49625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 496492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 496592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 49665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 49685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 49695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 49705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 497192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 49725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 49735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 49755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 49765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 497792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 49785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 498092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 498192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 498292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 498392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 49845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 49855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 498692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 498792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 498892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 49895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 499192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 499292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 49935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 499492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 499592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 499692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 499792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 499892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountType = c.getString(LookupByRawContactIdQuery.ACCOUNT_TYPE); 499992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 500092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 500192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 500292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 500392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 500492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 500592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 500692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 500792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 500892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 500992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 501092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 501192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 501292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 501392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 501492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 50155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 501792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 501892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 501992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 502092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 502192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 502292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 502392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 502492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 502592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 502692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 502792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 502892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 502992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 503092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 503192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_TYPE = 1; 503292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 503392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 503492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 503592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 503692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 503792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 50385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 50395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 50405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 50415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 504292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 504392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 50445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 50455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 50465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 50495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 50505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 50515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 50535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 50545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 50555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 50565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 50575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 50585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 50595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 50605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 50615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 50625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 506392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 506492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 506592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 50665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 50675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 50685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 50695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 50735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 50745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 50775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 507992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 508092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 508192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 508292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 508392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 508492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 508592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 508692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 508792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 508892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 508992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 5090ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 5091ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(db, rawContactId); 5092ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 5093ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 50945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 50955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 50965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 50975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 50985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 50995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 51015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 51025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 51045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 51055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 51075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 51085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 51095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 51105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 51115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 51125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 51135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 51145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 51155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 51165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 51185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 51195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 51235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 51245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 51255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 51265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 5129763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 5130763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 513182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5132916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 5133916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 5134916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 5135916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5136916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5137916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 5138916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 5139916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 5140916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 5141916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 5142916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String[] projection, String filter) { 5143916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5144916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5145916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 5146916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5147916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(" JOIN (SELECT " + 5148916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov RawContacts.CONTACT_ID + " AS snippet_contact_id"); 5149916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5150916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA_ID)) { 5151916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", " + DataColumns.CONCRETE_ID + " AS " 5152916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov + SearchSnippetColumns.SNIPPET_DATA_ID); 5153916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5154916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 51559c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA1)) { 51569c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA1 + " AS " + SearchSnippetColumns.SNIPPET_DATA1); 5157916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5158916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 51599c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA2)) { 51609c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA2 + " AS " + SearchSnippetColumns.SNIPPET_DATA2); 5161916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5162916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 51639c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA3)) { 51649c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA3 + " AS " + SearchSnippetColumns.SNIPPET_DATA3); 51659c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 51669c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov 51679c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA4)) { 51689c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA4 + " AS " + SearchSnippetColumns.SNIPPET_DATA4); 5169916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5170916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5171916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_MIMETYPE)) { 5172916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", (" + 5173916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov "SELECT " + MimetypesColumns.MIMETYPE + 5174916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " FROM " + Tables.MIMETYPES + 5175916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + MimetypesColumns._ID + "=" + DataColumns.MIMETYPE_ID + 5176916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov ") AS " + SearchSnippetColumns.SNIPPET_MIMETYPE); 5177916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5178916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5179916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS + 5180916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + DataColumns.CONCRETE_ID + 5181916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN ("); 5182916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5183916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // Construct a query that gives us exactly one data _id per matching contact. 5184916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // MIN stands in for ANY in this context. 5185916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append( 5186916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov "SELECT MIN(" + Tables.NAME_LOOKUP + "." + NameLookupColumns.DATA_ID + ")" + 5187916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5188916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5189916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " ON (" + RawContactsColumns.CONCRETE_ID 5190916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov + "=" + Tables.NAME_LOOKUP + "." + NameLookupColumns.RAW_CONTACT_ID + ")" + 5191916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + " GLOB '"); 5192916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(NameNormalizer.normalize(filter)); 5193916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 5194916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + ")" + 5195916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " GROUP BY " + RawContactsColumns.CONCRETE_CONTACT_ID); 5196916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5197916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(")) ON (" + Contacts._ID + "=snippet_contact_id)"); 5198916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5199916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 5200916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 5201916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5202916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5203916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void appendContactsTables(StringBuilder sb, Uri uri, String[] projection) { 5204763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 5205f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5206763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5207763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5208d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5209763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5210763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 5211b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 521282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 521382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 521482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 521582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 5216b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 521782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 521882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 521982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 522082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 522182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 52223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 52233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 5224a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 52253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 522682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 522782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 5228ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 5229763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 5230763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 5231763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 5232f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5233763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5234763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5235d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5236763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5237763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 5238763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 5239763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 5240763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 5241763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5242763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 524346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 524446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana // Note: currently, "export only" equals to "restricted", but may not in the future. 524546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana boolean excludeRestrictedData = readBooleanQueryParameter(uri, 524646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.FOR_EXPORT_ONLY, false); 524746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 5248f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 524946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 525046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana if (requestingPackage != null) { 525146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana excludeRestrictedData = excludeRestrictedData 525246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 525346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 525446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 525546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setProjectionMap(sRawContactsEntityProjectionMap); 525646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 525746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 525846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 525982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 526082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 526182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5262d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa // Note: currently, "export only" equals to "restricted", but may not in the future. 5263763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = readBooleanQueryParameter(uri, 5264d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa Data.FOR_EXPORT_ONLY, false); 5265763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 5266f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5267763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5268763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5269763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar excludeRestrictedData = excludeRestrictedData 5270d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5271763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5272763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 5273763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getDataView(excludeRestrictedData)); 527482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 527582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 52763296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated presence when requested 5277b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 527882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 52793296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 528082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 528182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 528282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 52833296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated status updates when requested 5284b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 528582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 528682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 528782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 528882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 528982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 52903296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 52913296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 529282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 52933296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 5294ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 52953296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 52963296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual presence when requested 52973296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 52983296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 52993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdates.DATA_ID + "=" 53003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 53013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 53023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 53033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual status updates when requested 53043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, 53053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS, 53063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_RES_PACKAGE, 53073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_ICON, 53083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_LABEL, 53093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_TIMESTAMP)) { 53103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 53113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 53123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 53133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 53143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 531582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 531682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 531782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 5318ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 5319ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 53200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 53210a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 53220a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5323b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 53240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 53250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 5326b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 53270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 53280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 53290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 53300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 53310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 5332b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 53330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 53340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 53350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 53360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 53370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 53380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 53390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 53400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 53410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 53420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setTables(sb.toString()); 53430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 53440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 53450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 53464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 5347f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 5348f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 5349e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5350e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 5351e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 5352e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 5353fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 5354fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 5355e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 5356e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5357e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 5358e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 5359e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 5360e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 53614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 53624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 53634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 53644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 53654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 53664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 53674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 53684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 53694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5370e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 5371f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 5372f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 5373e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5374e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 5375e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 5376e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 5377fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 5378fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 5379e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 5380e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5381e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 5382e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 5383e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 5384e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 5385e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 5386e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 5387e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 5388e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 5389e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 5390e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 5391e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 5392e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 5393e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5394e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 5395e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 5396e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 5397e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5398e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5399e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 54007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 5401c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 5402c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 5403c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 5404c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 5405c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 5406f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 5407f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String limitParam = getQueryParameter(uri, "limit"); 5408c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 5409c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5410c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5411c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 5412c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 5413c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 5414c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 5415c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 5416c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5417c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5418c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 5419c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 5420c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 5421c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5422c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5423c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5424c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 54255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 54265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 54275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 54285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 54295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 54305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 54315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 54325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 54335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 54345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 54355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 54365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 54375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 54395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 54405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 54415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 54435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 54445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 54465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 54475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 54495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 54505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 54525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 54535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 545500ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 5456d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 545770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 545870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 5459fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0"; 546070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 546170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 546270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 546370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 5464d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 546570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 546667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 54675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 54685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 5469619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5470619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5471619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 5472b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 5473b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 5474b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 5475b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 5476d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 5477e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov return openPhotoAssetFile(uri, mode, 5478e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=" + Contacts.PHOTO_ID + " AND " + RawContacts.CONTACT_ID + "=?", 5479e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 5480e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5481b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5482e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 5483e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov return openPhotoAssetFile(uri, mode, 5484e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=? AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'", 54854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 5486d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5487d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5488f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 548942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 549042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann mSelectionArgs1[0] = String.valueOf(lookupContactIdByLookupKey(mDb, lookupKey)); 549142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + "=?"; 549242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 549342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 549442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 549542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 549642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 549742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann outputRawContactsAsVCard(localStream, selection, mSelectionArgs1); 549842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return buildAssetFileDescriptor(localStream); 549942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 550042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 550142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 550242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 550342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 550442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 550542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 5506d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 5507d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 550842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 550942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 5510d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 551142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 5512d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 551342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 5514d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(lookupContactIdByLookupKey(mDb, lookupKey)); 551542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 551642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 551742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 551842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 5519d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5520d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 5521d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 5522d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 5523d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 5524d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann outputRawContactsAsVCard(localStream, selection, null); 5525d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 5526d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5527b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5528b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 5529fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("File does not exist", 5530fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov uri)); 5531b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5532b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5533b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5534e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov private AssetFileDescriptor openPhotoAssetFile(Uri uri, String mode, String selection, 5535e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String[] selectionArgs) 5536e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 5537e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 5538e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("Mode " + mode 5539e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 5540e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5541e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 5542e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 5543e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 5544e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 5545e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 5546e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, 5547e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov selectionArgs); 5548e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5549e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 5550d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 5551d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5552d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5553d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 5554d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 5555d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5556d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 5557d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 5558d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 5559d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 5560d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5561d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 5562d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 5563d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5564d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 5565d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 5566d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 5567b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5568d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 5569d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 5570d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 5571d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5572d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 5573d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5574d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5575d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5576d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 5577d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 5578d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 5579d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5580d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 5581d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 5582d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 55837a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 55847a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa new VCardComposer(context, VCardConfig.VCARD_TYPE_DEFAULT, false); 5585d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 5586d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5587f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 55887a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa if (!composer.init(selection, selectionArgs)) { 55897a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 5590d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 55917a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa } 5592d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5593d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 5594d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 5595d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 5596d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5597d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5598d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 5599d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5600b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 56014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 56024f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 5603a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 56044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 5605b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 5606be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 56072d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 5608b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 5609b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 5610b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 5611f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 561242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 5613f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 5614b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 5615be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 5616b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 5617b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 5618f481f22a9323fe338672f99b88b26c5f0725cd42David Brown case DATA: 5619f481f22a9323fe338672f99b88b26c5f0725cd42David Brown return Data.CONTENT_TYPE; 5620508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 5621b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 562248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 562348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 562448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 562548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 56269005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 56279005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 562848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 562948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 563048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 563148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 563248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 563348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 563448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 563548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 5636b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 5637b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 5638b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 5639b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 5640b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 5641b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 5642b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 5643b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 5644c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 5645c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 5646c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 5647c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 5648d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov 564961efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 565061efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 56514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 56524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 56537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 56545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void setDisplayName(long rawContactId, int displayNameSource, 56555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary, String displayNameAlternative, String phoneticName, 56565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int phoneticNameStyle, String sortKeyPrimary, String sortKeyAlternative) { 56575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(1, displayNameSource); 56585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 2, displayNamePrimary); 56595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 3, displayNameAlternative); 56605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 4, phoneticName); 56615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(5, phoneticNameStyle); 56625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 6, sortKeyPrimary); 56635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 7, sortKeyAlternative); 56645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(8, rawContactId); 566525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 56663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 56673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 566873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 566973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 567073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 567173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 5672a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.add(rawContactId); 567373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 567473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 5675c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 5676c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 5677c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 5678c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 5679c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 5680c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 5681653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 5682c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 5683653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 5684653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 5685c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 5686c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 5687c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 5688c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 5689c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 5690c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 5691c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 5692c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 5693c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 5694653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 5695c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 5696653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 5697653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 5698c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 5699c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 5700ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 5701813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public String insertNameLookupForEmail(long rawContactId, long dataId, String email) { 5702f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 5703813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 5704f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5705f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5706b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String address = mDbHelper.extractHandleFromEmailAddress(email); 5707b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (address == null) { 5708813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 5709f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5710f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5711f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 5712f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 5713813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return address; 5714f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5715f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5716f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5717f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 5718f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5719f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 5720f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 5721f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 5722f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5723f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5724f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 5725f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 5726f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5727f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5728a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 5729a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 5730a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 5731a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 5732a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 5733a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5734a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 5735a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 5736a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 5737a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5738a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5739f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5740d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name, 5741d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov int fullNameStyle) { 5742d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle); 5743f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5744f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5745f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 5746f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5747f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 5748f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 5749f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5750f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5751f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5752f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 5753f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 5754f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 5755f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5756f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5757f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5758f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 5759d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 5760f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5761f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5762f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 576348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov public void insertNameLookupForPhoneticName(long rawContactId, long dataId, 576448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov ContentValues values) { 576548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (values.containsKey(StructuredName.PHONETIC_FAMILY_NAME) 576648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov || values.containsKey(StructuredName.PHONETIC_GIVEN_NAME) 576748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov || values.containsKey(StructuredName.PHONETIC_MIDDLE_NAME)) { 576848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, 576948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_FAMILY_NAME), 577048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_MIDDLE_NAME), 577148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_GIVEN_NAME)); 577248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 577348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 577448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 577548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov public void insertNameLookupForPhoneticName(long rawContactId, long dataId, String familyName, 577648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov String middleName, String givenName) { 577748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.setLength(0); 577848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (familyName != null) { 577948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(familyName.trim()); 578048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 578148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (middleName != null) { 578248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(middleName.trim()); 578348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 578448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (givenName != null) { 578548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(givenName.trim()); 578648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 578748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 578848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (mSb.length() > 0) { 578948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookup(rawContactId, dataId, NameLookupType.NAME_COLLATION_KEY, 579048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov NameNormalizer.normalize(mSb.toString())); 579148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 57923b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov 57933b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov if (givenName != null) { 57943b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov // We want the phonetic given name to be used for search, but not for aggregation, 57953b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov // which is why we are using NAME_SHORTHAND rather than NAME_COLLATION_KEY 57963b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov insertNameLookup(rawContactId, dataId, NameLookupType.NAME_SHORTHAND, 57973b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov NameNormalizer.normalize(givenName.trim())); 57983b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov } 579948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 580048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 5801f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5802f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 5803f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5804f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 58055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(1, rawContactId); 58065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(2, dataId); 58075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(3, lookupType); 58085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mNameLookupInsert, 4, name); 5809f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 5810f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5811f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5812f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5813f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 5814f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5815f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 58165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupDelete.bindLong(1, dataId); 5817f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 5818f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5819f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 58202d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 5821d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5822d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 5823d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 5824d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 5825d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 5826d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 5827d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 5828e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 5829916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 5830916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 5831e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 5832e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 58335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 5834c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 58357318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam); 5836c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 5837c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5838c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 58397318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam) { 58407318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), true); 58415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 58425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 58435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 58447318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov boolean allowEmailMatch) { 5845d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5846dc947a9d03279eab0fb7c3b9d8ffbb492c1e2062Dmitri Plotnikov "SELECT " + NameLookupColumns.RAW_CONTACT_ID + 5847d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5848d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 5849d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 58505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 5851a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 5852a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 5853a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 58544cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao + NameLookupType.NAME_SHORTHAND + "," 5855f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee + NameLookupType.ORGANIZATION + "," 585689f1f71495aedc58252b3f58a46a036986c319d2Dmitri Plotnikov + NameLookupType.NAME_CONSONANTS); 585720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 585820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 585920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 586089f1f71495aedc58252b3f58a46a036986c319d2Dmitri Plotnikov sb.append("))"); 5861ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5862ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 58634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 58644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 58654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 58664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 5867b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 5868b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 5869b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 5870b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 5871b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 58724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 58734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 5874b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 5875b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5876b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5877caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 58785e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 58795e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 58805e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 58815e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 58825e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 58835e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 58845e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 58855e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 58865e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 58875e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 58885e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5889caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 5890caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 5891caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 5892df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 5893df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 5894caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 5895caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 5896caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5897caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 58986f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 5899caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 59006f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 5901caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5902f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 590373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 590473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov * Returns true if the specified account type is writable. 590573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 590673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov protected boolean isWritableAccount(String accountType) { 5907bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov if (accountType == null) { 5908bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 5909bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 5910bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 591173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov Boolean writable = mAccountWritability.get(accountType); 591273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 591373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 591473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 591573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 5916627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 5917627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 5918627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 5919627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 592073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov accountType.equals(sync.accountType)) { 592173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 592273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 5923627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5924627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5925627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 5926627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 5927627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 592873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 592973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 593073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 593173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 593273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 593373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.put(accountType, writable); 593473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 5935627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5936b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 5937f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 5938f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 5939f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5940f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 5941f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5942f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5943f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5944f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5945f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5946f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 5947f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5948f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5949f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5950f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5951f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 5952f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5953f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 5954f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 5955f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5956f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5957f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 5958f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 5959f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 5960f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 5961f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 5962f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5963f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5964f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 5965f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 5966f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 5967f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 5968f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5969f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5970f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5971f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5972f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5973f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 5974f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 5975f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5976f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 5977f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 5978f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 5979f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 5980f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5981f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5982f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5983f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5984f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 5985f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5986f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 5987f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5988f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5989f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5990f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 5991f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 5992f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 5993f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5994f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5995f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5996f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 5997f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 5998f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 5999f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 6000f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 6001f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6002f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6003f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 6004f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 60055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 60065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindString(SQLiteStatement stmt, int index, String value) { 60075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 60085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 60095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 60105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindString(index, value); 60115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 60125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 60135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 60145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindLong(SQLiteStatement stmt, int index, Number value) { 60155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 60165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 60175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 60185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindLong(index, value.longValue()); 60195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 60205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 60212a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 60222a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov protected boolean isAggregationUpgradeNeeded() { 60232a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 60242a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov return false; 60252a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov } 60262a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 60272a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_AGGREGATION_ALGORITHM, "1")); 60282a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov return version < PROPERTY_AGGREGATION_ALGORITHM_VERSION; 60292a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov } 60302a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 60312a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov protected void upgradeAggregationAlgorithm() { 60322a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov // This upgrade will affect very few contacts, so it can be performed on the 60332a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov // main thread during the initial boot after an OTA 60342a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 60352a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov Log.i(TAG, "Upgrading aggregation algorithm"); 60362a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov int count = 0; 60372a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 60382a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov try { 60392a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov mDb.beginTransaction(); 60402a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov Cursor cursor = mDb.query(true, 60412a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov Tables.RAW_CONTACTS + " r1 JOIN " + Tables.RAW_CONTACTS + " r2", 60422a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov new String[]{"r1." + RawContacts._ID}, 60432a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov "r1." + RawContacts._ID + "!=r2." + RawContacts._ID + 60442a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov " AND r1." + RawContacts.CONTACT_ID + "=r2." + RawContacts.CONTACT_ID + 60452a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_NAME + "=r2." + RawContacts.ACCOUNT_NAME + 60462a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_TYPE + "=r2." + RawContacts.ACCOUNT_TYPE, 60472a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov null, null, null, null, null); 60482a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov try { 60492a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov while (cursor.moveToNext()) { 60502a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov long rawContactId = cursor.getLong(0); 60512a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, 60522a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 60532a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov count++; 60542a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov } 60552a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov } finally { 60562a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov cursor.close(); 60572a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov } 60582a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov mContactAggregator.aggregateInTransaction(mDb); 60592a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov mDb.setTransactionSuccessful(); 60602a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov mDbHelper.setProperty(PROPERTY_AGGREGATION_ALGORITHM, 60612a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov String.valueOf(PROPERTY_AGGREGATION_ALGORITHM_VERSION)); 60622a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov } finally { 60632a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov mDb.endTransaction(); 60642a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 60652a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov Log.i(TAG, "Aggregation algorithm upgraded for " + count 60662a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov + " contacts, in " + (end - start) + "ms"); 60672a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov } 60682a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov } 60694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 6070