ContactsProvider2.java revision 7a3c645fa7db38449d34eb04d4e032fd079c3244
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 1997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.internal.content.SyncStateContentProviderHelper; 205b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport com.android.providers.contacts.ContactAggregator.AggregationSuggestionParameter; 2197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 2297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 2397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 2497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 2597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 2697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 2797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 2897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 2997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 3097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 3197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 3297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 3397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 3497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 3597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 3697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 3797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 3897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 3997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.vcard.VCardComposer; 4097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.vcard.VCardConfig; 4197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Lists; 4297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Maps; 4397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Sets; 4497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 45b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 46caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 475b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 48bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.Notification; 49bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.NotificationManager; 50bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.PendingIntent; 51c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 52568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 53568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 546ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 5535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 58627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.IContentService; 59bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.content.Intent; 60568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 613d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 62627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 6367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 64b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 654cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Taoimport android.content.res.Configuration; 661129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikovimport android.database.CharArrayBuffer; 674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 68ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.CursorWrapper; 69ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 7009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor; 7109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor.RowBuilder; 72a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 75c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 76892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikovimport android.location.Country; 77892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikovimport android.location.CountryDetector; 78892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikovimport android.location.CountryListener; 794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 80d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.net.Uri.Builder; 8151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikovimport android.os.AsyncTask; 826ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 83892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikovimport android.os.HandlerThread; 84d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 85892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikovimport android.os.Process; 86ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringertimport android.os.ParcelFileDescriptor; 87b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 880e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 893d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 90508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 913de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 92b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 9397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 9497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 9597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 9697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 9797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 9897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 9997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 10097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 10197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 10297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 103ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 1043de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 1055b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions; 1063de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 107d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory; 1085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.DisplayNameSources; 1095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.FullNameStyle; 1103de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 111bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.provider.ContactsContract.Intents; 1123de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 1135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.PhoneticNameStyle; 11409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 1153de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 116916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 1173de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 11882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 11997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.LiveFolders; 12097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.OpenableColumns; 12197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.SyncStateContract; 122a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 123a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 124c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 126d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 127b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 128d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 129d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 13042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.text.SimpleDateFormat; 1317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 13342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.util.Date; 134b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1350e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 137622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 138b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1390e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 140ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1465b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 147caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 148bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 149bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 150bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 152619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 153619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 154619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 159b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov * Property key for the legacy contact import version. The need for a version 1603d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1613d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 163b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final String PROPERTY_CONTACTS_IMPORTED = "contacts_imported_v1"; 164b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int PROPERTY_CONTACTS_IMPORT_VERSION = 1; 16551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final String PREF_LOCALE = "locale"; 1663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1670e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1680e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 169a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 171dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov private static final String TIMES_CONTACTED_SORT_COLUMN = "times_contacted_sort"; 1725e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 173d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 174dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov + TIMES_CONTACTED_SORT_COLUMN + " DESC, " 1759b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 176d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 177d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 178d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 179d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1806e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 1819b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 1829b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1839b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 1849b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 1856e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 1869b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 1879b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1889b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 1899b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 190de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 191de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 192d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 193d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 196a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_DATA = 1004; 1975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 2005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 201a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_PHOTO = 1009; 202f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 20342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann private static final int CONTACTS_AS_MULTI_VCARD = 1011; 2042149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov private static final int CONTACTS_LOOKUP_DATA = 1012; 2052149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ID_DATA = 1013; 206a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_ENTITIES = 1014; 207a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ENTITIES = 1015; 208a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ID_ENTITIES = 1016; 2094f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 2115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 2125ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 21346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 2144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2156bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2166bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 217ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 21848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 21948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 22048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 22148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 22248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 22348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 22448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 22548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 226a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2276bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 2286bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 229b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 230b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 231b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 23282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 23382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 2341f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 23531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 23631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 237eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 238eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 239ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 240ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 241ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 242ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 24335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 244b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 24535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 246c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 247c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 248c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 25446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 25546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 25609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 25709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 258d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES = 17001; 259d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES_ID = 17002; 260d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 2617a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private static final int COMPLETE_NAME = 18000; 2627a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 263dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID = 264dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 265dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME 266dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 267dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE 268dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_TYPE 269dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + " != 0"; 270dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 271dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID = 272dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 273dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 274dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 275dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 276dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND " 277dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + Groups.AUTO_ADD + " != 0"; 278dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 279dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String[] PROJECTION_GROUP_ID 280dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana = new String[]{Tables.GROUPS + "." + Groups._ID}; 281dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 282dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_GROUPMEMBERSHIP_DATA = DataColumns.MIMETYPE_ID + "=? " 283dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.GROUP_ROW_ID + "=? " 284dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.RAW_CONTACT_ID + "=?"; 285dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 286dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_STARRED_FROM_RAW_CONTACTS = 287dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT " + RawContacts.STARRED 288dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?"; 289dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 290d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 291f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 292f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 293f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 29467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 29567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2966cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 298f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 299ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 300ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 301d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 30267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 303d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 304ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 30614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 30767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 3083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 30988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 3103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 3113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 3125ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 3133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 314f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 31588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 31688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 31788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 31888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 31988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 32088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 32188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 322f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 3233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 3243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 32514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 3263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 3275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 3283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 329f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 3303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 3313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 33214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 333321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 33420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 33520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 336321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 337321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 33820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 33920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 340f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 34119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 34219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 34319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 34419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 345ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 346ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 347ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 34819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 34919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 35019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 351ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 352ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 35319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 35419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 355c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 356df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 357caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 35871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 35971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 36071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 36171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 36271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 36371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 36471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 36571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 36671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 36771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 36871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 36971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 37071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 37171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 372a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 373a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 374a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 375a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 376a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 377a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 378a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 379a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 380a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 381a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 382a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 383a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 384916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 385916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 386916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 387916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 388916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NICKNAME + "," + 389916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_SHORTHAND + "," + 390f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.ORGANIZATION + "," + 391f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.NAME_CONSONANTS; 392916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 393916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 394f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsColumns = ProjectionMap.builder() 395f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CUSTOM_RINGTONE) 396f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME) 397f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_ALTERNATIVE) 398f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_SOURCE) 399f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.IN_VISIBLE_GROUP) 400f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LAST_TIME_CONTACTED) 401f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LOOKUP_KEY) 402f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME) 403f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME_STYLE) 404f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHOTO_ID) 405f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SEND_TO_VOICEMAIL) 406f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_ALTERNATIVE) 407f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_PRIMARY) 408f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.STARRED) 409f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.TIMES_CONTACTED) 410f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 411f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 412f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsPresenceColumns = ProjectionMap.builder() 413f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 414f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE) 415f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 416f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 417f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 418f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 419f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 420f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 421f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 422f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 423f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 424f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 425f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 426f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 427f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 428f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 429f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSnippetColumns = ProjectionMap.builder() 430f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_MIMETYPE) 431f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_DATA_ID) 432f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_DATA1) 433f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_DATA2) 434f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_DATA3) 435f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_DATA4) 436f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 437f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 438f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 439f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactColumns = ProjectionMap.builder() 440f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_NAME) 441f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_TYPE) 442f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DIRTY) 443f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.NAME_VERIFIED) 444f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SOURCE_ID) 445f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.VERSION) 446f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 447f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 448f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactSyncColumns = ProjectionMap.builder() 449f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC1) 450f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC2) 451f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC3) 452f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC4) 453f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 454f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 455f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataColumns = ProjectionMap.builder() 456f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA1) 457f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA2) 458f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA3) 459f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA4) 460f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA5) 461f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA6) 462f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA7) 463f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA8) 464f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA9) 465f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA10) 466f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA11) 467f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA12) 468f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA13) 469f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA14) 470f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA15) 471f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA_VERSION) 472f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_PRIMARY) 473f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_SUPER_PRIMARY) 474f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.MIMETYPE) 475f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RES_PACKAGE) 476f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC1) 477f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC2) 478f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC3) 479f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC4) 480f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(GroupMembership.GROUP_SOURCE_ID) 481f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 482f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 483f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactPresenceColumns = ProjectionMap.builder() 484f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 485f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.PRESENCE) 486f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 487f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.CHAT_CAPABILITY) 488f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 489f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 490f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 491f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 492f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 493f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 494f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 495f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 496f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 497f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 498f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 499f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 500f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataPresenceColumns = ProjectionMap.builder() 501f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.PRESENCE, Tables.PRESENCE + "." + StatusUpdates.PRESENCE) 502f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CHAT_CAPABILITY, Tables.PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 503f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS, StatusUpdatesColumns.CONCRETE_STATUS) 504f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_TIMESTAMP, StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 505f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_RES_PACKAGE, StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 506f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_LABEL, StatusUpdatesColumns.CONCRETE_STATUS_LABEL) 507f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_ICON, StatusUpdatesColumns.CONCRETE_STATUS_ICON) 508f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 509f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 510038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 511f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sCountProjectionMap = ProjectionMap.builder() 512f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(BaseColumns._COUNT, "COUNT(*)") 513f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 514f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 515e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 516f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionMap = ProjectionMap.builder() 517f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts._ID) 518f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 519f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.NAME_RAW_CONTACT_ID) 520f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 521f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsPresenceColumns) 522f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 523f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 524916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 525f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionWithSnippetMap = ProjectionMap.builder() 526f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 527f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sSnippetColumns) 528f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 529916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5305e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 531f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentStarredProjectionMap = ProjectionMap.builder() 532f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 533f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(TIMES_CONTACTED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 534f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 535f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 536f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder() 537f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 538f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(TIMES_CONTACTED_SORT_COLUMN, Contacts.TIMES_CONTACTED) 539f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 540f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 541f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 542f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsVCardProjectionMap = ProjectionMap.builder() 543f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME + " || '.vcf'") 544f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.SIZE, "NULL") 545f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 546f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 547ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 548f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactsProjectionMap = ProjectionMap.builder() 549f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 550f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 551f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 552f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_PRIMARY) 553f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_ALTERNATIVE) 554f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_SOURCE) 555f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME) 556f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME_STYLE) 557f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_PRIMARY) 558f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_ALTERNATIVE) 559f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.TIMES_CONTACTED) 560f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.LAST_TIME_CONTACTED) 561f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CUSTOM_RINGTONE) 562f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SEND_TO_VOICEMAIL) 563f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 564f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.AGGREGATION_MODE) 565f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 566f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 567f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 568f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 569a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the raw entity view*/ 570f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawEntityProjectionMap = ProjectionMap.builder() 571f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 572f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 573f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.Entity.DATA_ID) 574f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.IS_RESTRICTED) 575f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 576f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 577f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 578f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 579f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 580f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 581f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 582a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the contact entity view*/ 583f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sEntityProjectionMap = ProjectionMap.builder() 584f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity._ID) 585f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.CONTACT_ID) 586f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.RAW_CONTACT_ID) 587f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DATA_ID) 588f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.NAME_RAW_CONTACT_ID) 589f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DELETED) 590f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.IS_RESTRICTED) 591f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 592f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 593f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 594f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 595f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 596f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 597f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 598f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 5994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 600f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataProjectionMap = ProjectionMap.builder() 601f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID) 602f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RAW_CONTACT_ID) 603f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CONTACT_ID) 604f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.NAME_RAW_CONTACT_ID) 605f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 606f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 607f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 608f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 609f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 610f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 611f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 613f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDistinctDataProjectionMap = ProjectionMap.builder() 614f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID, "MIN(" + Data._ID + ")") 615f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 616f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 617f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 618f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 619f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 620f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 621f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 623f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sPhoneLookupProjectionMap = ProjectionMap.builder() 624f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup._ID, "contacts_view." + Contacts._ID) 625f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LOOKUP_KEY, "contacts_view." + Contacts.LOOKUP_KEY) 626f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.DISPLAY_NAME, "contacts_view." + Contacts.DISPLAY_NAME) 627f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LAST_TIME_CONTACTED, "contacts_view." + Contacts.LAST_TIME_CONTACTED) 628f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TIMES_CONTACTED, "contacts_view." + Contacts.TIMES_CONTACTED) 629f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.STARRED, "contacts_view." + Contacts.STARRED) 630f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.IN_VISIBLE_GROUP, "contacts_view." + Contacts.IN_VISIBLE_GROUP) 631f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.PHOTO_ID, "contacts_view." + Contacts.PHOTO_ID) 632f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.CUSTOM_RINGTONE, "contacts_view." + Contacts.CUSTOM_RINGTONE) 633f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.HAS_PHONE_NUMBER, "contacts_view." + Contacts.HAS_PHONE_NUMBER) 634f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.SEND_TO_VOICEMAIL, "contacts_view." + Contacts.SEND_TO_VOICEMAIL) 635f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.NUMBER, Phone.NUMBER) 636f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TYPE, Phone.TYPE) 637f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LABEL, Phone.LABEL) 638f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 639f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 640ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 641f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsProjectionMap = ProjectionMap.builder() 642f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups._ID) 643f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_NAME) 644f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_TYPE) 645f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SOURCE_ID) 646f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DIRTY) 647f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.VERSION) 648f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.RES_PACKAGE) 649f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE) 650f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE_RES) 651f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.GROUP_VISIBLE) 652f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYSTEM_ID) 653f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DELETED) 654f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.NOTES) 655f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SHOULD_SYNC) 656f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.FAVORITES) 657f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.AUTO_ADD) 658f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC1) 659f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC2) 660f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC3) 661f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC4) 662f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 663f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 664ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 665f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsSummaryProjectionMap = ProjectionMap.builder() 666f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sGroupsProjectionMap) 667f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_COUNT, 668f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 669f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS 670f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP 671f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Clauses.BELONGS_TO_GROUP 672f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ")") 673f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_WITH_PHONES, 674f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 675f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS 676f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP 677f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Clauses.BELONGS_TO_GROUP 678f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ")") 679f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 680f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 681373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 682f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sAggregationExceptionsProjectionMap = ProjectionMap.builder() 683f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id") 684f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.TYPE) 685f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID1) 686f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID2) 687f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 688f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 689eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 690f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSettingsProjectionMap = ProjectionMap.builder() 691f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_NAME) 692f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_TYPE) 693f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_VISIBLE) 694f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.SHOULD_SYNC) 695f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ANY_UNSYNCED, 696f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 697f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ",(SELECT " 698f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "(CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL" 699f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 700f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE MIN(" + Groups.SHOULD_SYNC + ")" 701f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)" 702f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.GROUPS 703f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 704f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_NAME 705f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 706f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0" 707f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 708f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE 0" 709f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)") 710f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_COUNT, 711f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 712f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 713f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 714f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 715f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 716f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 717f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_WITH_PHONES, 718f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 719f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 720f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 721f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Contacts.HAS_PHONE_NUMBER 722f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 723f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 724f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 725f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 726f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 72782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 728f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStatusUpdatesProjectionMap = ProjectionMap.builder() 729f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PresenceColumns.RAW_CONTACT_ID) 730f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.DATA_ID, DataColumns.CONCRETE_ID) 731f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_ACCOUNT) 732f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_HANDLE) 733f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PROTOCOL) 734f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 735f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // properly enforce uniqueness of null values 736f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CUSTOM_PROTOCOL, 737f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL + "=''" 738f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN NULL" 739f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END)") 740f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PRESENCE) 741f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CHAT_CAPABILITY) 742f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS) 743f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_TIMESTAMP) 744f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_RES_PACKAGE) 745f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_ICON) 746f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_LABEL) 747f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 748f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 750f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sLiveFoldersProjectionMap = ProjectionMap.builder() 751f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders._ID, Contacts._ID) 752f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders.NAME, Contacts.DISPLAY_NAME) 753f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 754f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // for contacts without a photo 755f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // .add(LiveFolders.ICON_BITMAP, Photos.DATA) 756f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 757f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 758d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** Contains {@link Directory} columns */ 759f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDirectoryProjectionMap = ProjectionMap.builder() 760f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory._ID) 761f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.PACKAGE_NAME) 762f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.TYPE_RESOURCE_ID) 763f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DISPLAY_NAME) 764f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DIRECTORY_AUTHORITY) 765f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_TYPE) 766f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_NAME) 767f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.EXPORT_SUPPORT) 768f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 7697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 7709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 7719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 7729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 7739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 7749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 7759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 7762526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 7772526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 778bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 779bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 780bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 781bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 78251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 783c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 784c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 7853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 786c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 7873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 78825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 78982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 790a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 791f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 792f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 793a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 794a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 795a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 7960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 797a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 798f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov private SQLiteStatement mResetNameVerifiedForOtherRawContacts; 799a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 800f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 801f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 8021129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdStructuredName; 8031129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdOrganization; 8041129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdNickname; 8051129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdPhone; 806f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 8071129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 8081129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 8092526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 8102526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 811f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 812f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 8134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 8144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 815a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 816d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 817d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 818a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA); 819a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES); 8203653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 8213653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 8222d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 8232d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 824a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO); 825c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); 8265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 8275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 8282149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA); 8295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 8302149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", 8312149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov CONTACTS_LOOKUP_ID_DATA); 832a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", 833a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ENTITIES); 834a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", 835a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ID_ENTITIES); 836f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 83742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 83842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 8395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 840ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 841ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 8425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 8433653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 8445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 8455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 8465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 84746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 84846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 84946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 850b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 8514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 8524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 853ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 85448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 8555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 856ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 8574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 85848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 8595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 8605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 8614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 862ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 86348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 8641f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 865ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 866ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 867ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 868ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 86935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 870b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 871b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 87235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 873a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 874b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 875b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 876b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 877b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 8784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 879eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 880eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 88182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 88282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 8831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 884c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 885c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 886c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 887c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 8882d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 889c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 890c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 8911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 8921b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 8931b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 8941b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 8951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 8961b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 8971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 8981b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 89909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 90009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 901d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 902d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories", DIRECTORIES); 903d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories/#", DIRECTORIES_ID); 9047a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 9057a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "complete_name", COMPLETE_NAME); 90619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 90719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 908d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static class DirectoryInfo { 909d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String authority; 910d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountName; 911d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountType; 912d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 913d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 914d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 915d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Cached information about contact directories. 916d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 917d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private HashMap<String, DirectoryInfo> mDirectoryCache; 918d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 9193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 9213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 9233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 925653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 9263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9271129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov @SuppressWarnings("all") 9283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 9293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 930a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 931a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 932a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 933a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 934a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 935a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 936a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 937a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 9383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 940653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 941653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 942b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 943653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 944653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 945653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 946653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 9473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 9493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 951e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 952e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 953e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 954e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 955653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 956e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 957e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 958e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 9593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 9633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 964813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * 965813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * @return true if update changed something 9663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 967813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 968f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 96914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 97014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 971653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 972653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 973653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 974653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 975653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 976653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 977653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 978653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 979653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 980653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 981653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 982653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 983653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 984653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 985653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 986653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 987653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 9884da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 9894da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " =?", mSelectionArgs1); 990653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 991653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 992f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 993653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 994653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 995813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 996813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 9973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 100014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 100114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 100214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 10034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10044da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=?", mSelectionArgs1); 10054da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 10064da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=?", mSelectionArgs1); 10073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 10085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 10093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 10113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 10144da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov long mimeTypeId = getMimeTypeId(); 1015e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 1016e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 10174da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 10184da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = db.query(DataDeleteQuery.TABLE, 10194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov DataDeleteQuery.CONCRETE_COLUMNS, 10204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Data.RAW_CONTACT_ID + "=?" + 10214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov " AND " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId, 10224da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 10233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 1024e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 102514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 1026f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 1027e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 1028e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 1029e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 1030e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 10313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 10333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 10343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10354da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (primaryId != -1) { 10364da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov setIsPrimary(rawContactId, primaryId, mimeTypeId); 10374da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 1038e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1039e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1040e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 1041e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 1042e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 1043e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 1044e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1045e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 10463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 104825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 1049285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1050d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(db, rawContactId); 1051fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(db, rawContactId); 1052285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 10533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1054a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1055622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1056622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 1057813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * as baseline, but augmented with any updates. Returns null if there is 1058813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * no change. 1059622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1060622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 1061622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 1062813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov boolean changing = false; 1063622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 10644da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10654da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=?", 10664da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 1067622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 1068622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 1069622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 1070622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 1071813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov final String value = cursor.getString(i); 1072813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!changing && update.containsKey(key)) { 1073813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov Object newValue = update.get(key); 1074813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String newString = newValue == null ? null : newValue.toString(); 1075813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov changing |= !TextUtils.equals(newString, value); 1076813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1077813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov values.put(key, value); 1078622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1079622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1080622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 1081622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 1082622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1083813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!changing) { 1084813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 1085813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1086813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1087622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 1088622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 1089622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 10903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 10933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 10953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 10963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1100622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 11013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1102622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 11033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1104622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 11053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1109622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 111014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 111114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 111214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1113f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1114d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov Integer fullNameStyle = values.getAsInteger(StructuredName.FULL_NAME_STYLE); 1115d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name, 111651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov fullNameStyle != null 111751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov ? mNameSplitter.getAdjustedFullNameStyle(fullNameStyle) 111851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov : FullNameStyle.UNDEFINED); 111948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, values); 112025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1121813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 112214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 112314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 112414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 112514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1126813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1127f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1128622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1129622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1130cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1131622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1132813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1133813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1134813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1135813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1136622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 113714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1138f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 11397ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME) || 11407ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov values.containsKey(StructuredName.PHONETIC_FAMILY_NAME) || 11417ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov values.containsKey(StructuredName.PHONETIC_MIDDLE_NAME) || 11427ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov values.containsKey(StructuredName.PHONETIC_GIVEN_NAME)) { 11437ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov augmented.putAll(values); 11447ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov String name = augmented.getAsString(StructuredName.DISPLAY_NAME); 1145f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 11467ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov Integer fullNameStyle = augmented.getAsInteger(StructuredName.FULL_NAME_STYLE); 1147d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name, 114851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov fullNameStyle != null 114951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov ? mNameSplitter.getAdjustedFullNameStyle(fullNameStyle) 115051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov : FullNameStyle.UNDEFINED); 11517ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, augmented); 115214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 115325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1154813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1155813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 115614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 115714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 115814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 115914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 116014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 116114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 116214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 116314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 116414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1165f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 116625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1167813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 116814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 11693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1172622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 11733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1174622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1175622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1176622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1177622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 11783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1179622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1180622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1181622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1182622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1183622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1184622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 11857a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov public void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 118667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1187622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 118867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 118967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1190622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1191622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 11928c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1193622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1194622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 119567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 119667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 119767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 119867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 119967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 120067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 12018c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1202622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 12034cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao // As the name could be changed, let's guess the name style again. 12044cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao name.fullNameStyle = FullNameStyle.UNDEFINED; 12054cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mSplitter.guessNameStyle(name); 1206ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao int unadjustedFullNameStyle = name.fullNameStyle; 1207ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao name.fullNameStyle = mSplitter.getAdjustedFullNameStyle(name.fullNameStyle); 12085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov final String joined = mSplitter.join(name, true); 1209622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 12105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 1211ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao update.put(StructuredName.FULL_NAME_STYLE, unadjustedFullNameStyle); 12125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, name.phoneticNameStyle); 12134cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } else if (touchedUnstruct && touchedStruct){ 1214d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov if (!update.containsKey(StructuredName.FULL_NAME_STYLE)) { 1215d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov update.put(StructuredName.FULL_NAME_STYLE, 1216d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mSplitter.guessFullNameStyle(unstruct)); 12174cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1218d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov if (!update.containsKey(StructuredName.PHONETIC_NAME_STYLE)) { 1219d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, 1220d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mSplitter.guessPhoneticNameStyle(unstruct)); 12214cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1222622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1223622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1224622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1225622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1226622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1227622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1228622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1229622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1230622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1231622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1232622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1233622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1234622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1235622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1236622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1237622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1238622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1239622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1240622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1241813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1242f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1243622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1244622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1245813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1246813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1247813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1248813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1249622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1250f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1251813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 1252622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1253622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1254622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1255622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1256622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1257622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1258622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1259622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1260622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1261622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1262622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1263622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1264622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1265622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1266622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1267622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1268622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1269622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 127067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 127167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 127267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 127367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1274622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1275622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1276622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1277622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1278622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1279622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 128067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 128167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 128267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1283622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1284622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1285622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 12863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 12913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 12933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 12943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 12963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 12973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 12983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 12993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1303622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1304622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1305622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1307622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1308813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1309f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1310622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1311622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1312813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1313813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1314813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1315622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1316813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return super.update(db, values, c, callerIsSyncAdapter); 1317622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1319622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1320622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1321622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1322622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1323622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1324622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1325622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1326622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 13273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1328622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1329622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1330622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1331622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1332622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 13373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 13393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 13403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1344a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1345a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1346a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1347a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1348a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 134925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1350a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1351a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 13523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 1355813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1356f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1357813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1358813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1359813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 136014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 136131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov boolean containsCompany = values.containsKey(Organization.COMPANY); 136231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov boolean containsTitle = values.containsKey(Organization.TITLE); 136331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsCompany || containsTitle) { 1364813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1365813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1366813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 136731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov String company; 136831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 136931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsCompany) { 137031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov company = values.getAsString(Organization.COMPANY); 137131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } else { 137231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 137331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov company = DatabaseUtils.stringForQuery(db, 137431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov "SELECT " + Organization.COMPANY + 137531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " FROM " + Tables.DATA + 137631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " WHERE " + Data._ID + "=?", mSelectionArgs1); 137731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 137831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 137931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov String title; 138031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsTitle) { 138131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov title = values.getAsString(Organization.TITLE); 138231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } else { 138331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 138431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov title = DatabaseUtils.stringForQuery(db, 138531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov "SELECT " + Organization.TITLE + 138631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " FROM " + Tables.DATA + 138731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " WHERE " + Data._ID + "=?", mSelectionArgs1); 138831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 138931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 139031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov deleteNameLookup(dataId); 139131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov insertNameLookupForOrganization(rawContactId, dataId, company, title); 139231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 139331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 139431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 1395813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 139614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 139714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 139814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 139914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1400a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 140114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 140214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 140314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 140425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1405a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 140614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 140714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 140814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 140914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 14103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 14113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 14123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 14133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 14143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 14153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 14163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1420e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1421e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1422e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1423e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1424e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1425e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1426e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 14275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1428813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String email = values.getAsString(Email.DATA); 142914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 143014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 143114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 143225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1433813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String address = insertNameLookupForEmail(rawContactId, dataId, email); 1434813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (address != null) { 1435813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1436813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 143714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 143814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 143914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 144014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1441813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1442f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1443813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1444813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1445813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 144614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1447b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (values.containsKey(Email.DATA)) { 1448813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1449813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1450813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1451b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String address = values.getAsString(Email.DATA); 1452b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov deleteNameLookup(dataId); 1453b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 1454b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1455813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1456b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov } 1457813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1458813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 145914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 146014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 146214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 146314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 146414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 146514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 146714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1468f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 146925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1470813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 147114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1472e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1473e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1474e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1475e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1476e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1477e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1478e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1479e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1480e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1481e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1482e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1483e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1484e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1485e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 148614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 148714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 148814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 148914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 149014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 149114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 149214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 149314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 149414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 149514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 149614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 149714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1498813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!TextUtils.isEmpty(nickname)) { 1499813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1500813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1501813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1502813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 150314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 150414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 150514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 150614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1507813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1508f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 150914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 151014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 151114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1512813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1513813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1514813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 151514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1516b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (values.containsKey(Nickname.NAME)) { 1517b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 1518b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov deleteNameLookup(dataId); 1519b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1520b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1521813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1522b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov } 1523813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1524813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 152514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 152614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 152714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 152814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 152914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 153014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 153114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 153214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 153314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1534f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 153525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1536813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 153714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 153814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 153914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 154014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 15413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 15423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 15443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 15453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 15485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 15490b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 15500b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 15510b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 1552892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String numberE164 = 1553892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.formatNumberToE164(number, getCurrentCountryIso()); 1554892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (numberE164 != null) { 1555892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, numberE164); 1556892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 15570b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1558653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1559892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, numberE164); 1560285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 156125abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1562892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (numberE164 != null) { 1563813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1564813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 15650b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 15660b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 15670b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1568653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1569653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1570653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1571653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1572813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1573f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1574813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String number = null; 1575813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String normalizedNumber = null; 1576892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String numberE164 = null; 15770b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 1578813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov number = values.getAsString(Phone.NUMBER); 1579892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (number != null) { 1580892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov numberE164 = 1581892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.formatNumberToE164(number, getCurrentCountryIso()); 1582892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 1583892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (numberE164 != null) { 1584892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, numberE164); 1585892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 1586813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1587653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1588813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1589813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1590813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1591653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1592813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 1593813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1594813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1595892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, numberE164); 1596285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 159725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1598813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 15990b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1600813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 160114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 160214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 160314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 160414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 160514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 160614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 160714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 160814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 160914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 161014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1611285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 161225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1613813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 161414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1615653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1616653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1617653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1618892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String number, String numberE164) { 1619892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 1620892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=?", mSelectionArgs1); 1621e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1622892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String normalizedNumber = PhoneNumberUtils.normalizeNumber(number); 1623892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (!TextUtils.isEmpty(normalizedNumber)) { 1624892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 1625892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1626892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1627892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 1628892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.MIN_MATCH, 1629892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber)); 1630892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov db.insert(Tables.PHONE_LOOKUP, null, phoneValues); 1631892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov 1632892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (numberE164 != null && !numberE164.equals(normalizedNumber)) { 1633892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, numberE164); 1634892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.MIN_MATCH, 1635892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.toCallerIDMinMatch(numberE164)); 1636892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov db.insert(Tables.PHONE_LOOKUP, null, phoneValues); 1637892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 1638892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 1639e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 16403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 16423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 16433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 16443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 16453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 16463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 16473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 16483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 16493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 16503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 16513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 16523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 16533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 16543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1658653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1659653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1660dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_RAW_CONTACT_ID = RawContacts._ID + "=?"; 1661dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1662dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String QUERY_COUNT_FAVORITES_GROUP_MEMBERSHIPS_BY_RAW_CONTACT_ID = 1663dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT COUNT(*) FROM " + Tables.DATA + " LEFT OUTER JOIN " + Tables .GROUPS 1664dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " ON " + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID 1665dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + GroupsColumns.CONCRETE_ID 1666dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " WHERE " + DataColumns.MIMETYPE_ID + "=?" 1667dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Tables.DATA + "." + GroupMembership.RAW_CONTACT_ID + "=?" 1668dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + "!=0"; 1669dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1670653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1671653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1672653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1673653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1674653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1675653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1676653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 16770be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1678dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (hasFavoritesGroupMembership(db, rawContactId)) { 1679dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContactsStar(db, rawContactId, true /* starred */); 1680dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 16810be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 16820be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1683653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1684653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1685653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1686813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1687f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 168814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1689dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean wasStarred = hasFavoritesGroupMembership(db, rawContactId); 1690653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1691813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1692813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1693813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1694dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean isStarred = hasFavoritesGroupMembership(db, rawContactId); 1695dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (wasStarred != isStarred) { 1696dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContactsStar(db, rawContactId, isStarred); 1697dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 16980be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 1699813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 17000be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 17010be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 1702dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateRawContactsStar(SQLiteDatabase db, long rawContactId, boolean starred) { 1703dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues rawContactValues = new ContentValues(); 1704dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactValues.put(RawContacts.STARRED, starred ? 1 : 0); 1705dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (db.update(Tables.RAW_CONTACTS, rawContactValues, SELECTION_RAW_CONTACT_ID, 1706dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}) > 0) { 1707dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mContactAggregator.updateStarred(rawContactId); 1708dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1709dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1710dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1711dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private boolean hasFavoritesGroupMembership(SQLiteDatabase db, long rawContactId) { 1712dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final long groupMembershipMimetypeId = mDbHelper 1713dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 1714dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean isStarred = 0 < DatabaseUtils 1715dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana .longForQuery(db, QUERY_COUNT_FAVORITES_GROUP_MEMBERSHIPS_BY_RAW_CONTACT_ID, 1716dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(groupMembershipMimetypeId), Long.toString(rawContactId)}); 1717dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return isStarred; 1718dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1719dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 17200be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 17210be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 17220be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1723dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean wasStarred = hasFavoritesGroupMembership(db, rawContactId); 17240be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 1725dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean isStarred = hasFavoritesGroupMembership(db, rawContactId); 1726dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (wasStarred && !isStarred) { 1727dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContactsStar(db, rawContactId, false /* starred */); 1728dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 17290be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 17300be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 17310be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 17320be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 17330be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1734b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 17350be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1736b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 17370be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1738653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1739653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1740653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1741653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1742653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1743653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1744653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1745653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1746653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1747653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1748653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1749653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1750653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1751653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1752653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1753653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1754653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1755653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1756653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1757653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1758653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1759653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1760653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1761653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1762ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId, 1763ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.get(rawContactId)); 1764653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1765653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1766653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1767653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1768653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1769653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1770a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1771a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1772a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1773a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1774a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1775a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1776a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1777a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1778a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1779285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1780285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1781285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1782a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1783a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1784a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1785a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1786813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1787f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1788a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1789813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1790813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1791813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1792813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1793a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1794813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 1795a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1796a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1797a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1798a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1799a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1800a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1801a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1802a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1803a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1804a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1805a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1806ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov /** 1807ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 1808ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1809ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1810ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov public class GroupIdCacheEntry { 1811ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1812ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 1813ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1814ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1815ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1816a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 18173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 1818b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 181931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 18204097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1821f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1822315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1823622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1824622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1825ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1826ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1827ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // is a list of groups with this group id. 1828ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1829ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 183072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private ContactDirectoryManager mContactDirectoryManager; 1831622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1832f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1833a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1834d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1835a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 183620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 18371129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private CharArrayBuffer mCharArrayBuffer = new CharArrayBuffer(128); 18385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private NameSplitter.Name mName = new NameSplitter.Name(); 183973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 184020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 184109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 184209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 1843ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 184473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1845ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<Long, Account> mInsertedRawContacts = Maps.newHashMap(); 1846b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1847a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private HashSet<Long> mDirtyRawContacts = Sets.newHashSet(); 1848b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1849de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 18501a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 18511a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 185281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 185381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 18544cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 1855d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1856892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov private String mCurrentCountryIso; 185773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 185872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 18594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 18604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1861de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1862ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1863ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1864ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1865ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1866ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1867ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1868ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 186935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1870ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 1871de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1872b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 187372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager = new ContactDirectoryManager(this); 1874a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1875b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1876b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 1877653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 187851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov initForDefaultLocale(); 1879d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1880b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mSetPrimaryStatement = mDb.compileStatement( 1881653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1882653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1883653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1884653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1885653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1886b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mSetSuperPrimaryStatement = mDb.compileStatement( 1887653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1888653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1889653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1890653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1891653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1892653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1893653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1894653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1895653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1896653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1897653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1898b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mRawContactDisplayNameUpdate = mDb.compileStatement( 189925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 19005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov " SET " + 19015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE + "=?," + 19025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY + "=?," + 19035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," + 19045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME + "=?," + 19055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE + "=?," + 19065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY + "=?," + 19075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE + "=?" + 190825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 19093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1910b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mLastStatusUpdate = mDb.compileStatement( 1911a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.CONTACTS + 1912a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1913a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1914a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1915a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1916a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1917a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1918a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1919a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1920a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1921a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 19220a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 19230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1924a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " LIMIT 1)" + 1925a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1926e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1927b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mNameLookupInsert = mDb.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1928f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1929f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1930f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1931b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mNameLookupDelete = mDb.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1932f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1933f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1934b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateInsert = mDb.compileStatement( 1935a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1936a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 19370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 19380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 19390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 19400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 19410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 1942a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1943b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateReplace = mDb.compileStatement( 1944a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1945a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 19460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 19470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 19480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 19490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 19500a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 19510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1952a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1953b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateAutoTimestamp = mDb.compileStatement( 1954a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 19550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 19560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 1957a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 19580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 19590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 1960b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusAttributionUpdate = mDb.compileStatement( 19610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 19620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 19630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 19640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 19650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1966a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1967b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateDelete = mDb.compileStatement( 1968a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1969a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1970a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 1971f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // When setting NAME_VERIFIED to 1 on a raw contact, reset it to 0 1972f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // on all other raw contacts in the same aggregate 1973b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mResetNameVerifiedForOtherRawContacts = mDb.compileStatement( 1974f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 1975f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " SET " + RawContacts.NAME_VERIFIED + "=0" + 1976f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=(" + 1977f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1978f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1979f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?)" + 1980f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " AND " + RawContacts._ID + "!=?"); 1981f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 1982f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1983f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 19841129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdStructuredName = mDbHelper.getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE); 19851129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdOrganization = mDbHelper.getMimeTypeId(Organization.CONTENT_ITEM_TYPE); 19861129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdNickname = mDbHelper.getMimeTypeId(Nickname.CONTENT_ITEM_TYPE); 19871129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdPhone = mDbHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 198804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov 1989bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov verifyAccounts(); 1990bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 199165ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 199265ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov importLegacyContactsAsync(); 199380952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov } else { 199480952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov verifyLocale(); 199565ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov } 199665ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 199772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov startContactDirectoryManager(); 199872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1999b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return (mDb != null); 20004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 20014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2002892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov protected synchronized String getCurrentCountryIso() { 2003892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (mCurrentCountryIso == null) { 2004892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov final CountryDetector countryDetector = 2005892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov (CountryDetector)getContext().getSystemService(Context.COUNTRY_DETECTOR); 2006892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov mCurrentCountryIso = countryDetector.detectCountry().getCountryIso(); 2007892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov // Start a new thread to listen to the country change. 2008892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov (new HandlerThread("country listener", Process.THREAD_PRIORITY_BACKGROUND) { 2009892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov @Override 2010892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov protected void onLooperPrepared() { 2011892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov countryDetector.addCountryListener(new CountryListener() { 2012892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov public void onCountryDetected(Country country) { 2013892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov mCurrentCountryIso = country.getCountryIso(); 2014892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 2015892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov }, null); 2016892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 2017892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov }).start(); 2018892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 2019892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov return mCurrentCountryIso; 2020892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 2021892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov 2022ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao private void initDataRowHandlers() { 2023ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers = new HashMap<String, DataRowHandler>(); 2024ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao 2025ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 2026ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 2027ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 2028ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 2029ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 2030ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 2031ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 2032ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 2033ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 2034ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao new StructuredNameRowHandler(mNameSplitter)); 2035ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 2036ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao new StructuredPostalRowHandler(mPostalSplitter)); 2037ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 2038ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 2039ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao } 204072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 204151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 2042767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov * Visible for testing. 2043767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov */ 2044767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 2045767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov return new PhotoPriorityResolver(context); 2046767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov } 2047767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov 2048767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 204951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 205051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 205104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 20524cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 205304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov mNameSplitter = mDbHelper.createNameSplitter(); 20544cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 20554cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 205651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mCommonNicknameCache = new CommonNicknameCache(mDbHelper.getReadableDatabase()); 2057cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 20585b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper, 20595b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov createPhotoPriorityResolver(getContext()), mNameSplitter, mCommonNicknameCache); 20605b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 20615b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 2062ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao initDataRowHandlers(); 20634cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 20644cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 206553fac8f99f3884c372c907a76766d27fa9e1d95fDmitri Plotnikov public void onLocaleChanged() { 20664f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL) { 20674f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov return; 20684f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov } 20694f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 207051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov initForDefaultLocale(); 207151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov verifyLocale(); 20724cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 207351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2074c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 2075c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 2076c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 2077c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 2078c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 207951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 208051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 208151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 208251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 208351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 208451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 208551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 208651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void verifyLocale() { 2087f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 2088f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 2089f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 2090f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 2091f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 2092f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 209351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 209451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 209551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 209651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 209751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 209851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 209951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 210051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 210151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 210251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 210351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov AsyncTask<Integer, Void, Void> task = new AsyncTask<Integer, Void, Void>() { 210451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 210551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int savedProviderStatus; 210651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 210751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov @Override 210851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected Void doInBackground(Integer... params) { 210951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov savedProviderStatus = params[0]; 211051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mDbHelper.setLocale(ContactsProvider2.this, currentLocale); 211151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return null; 211251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 211351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 211451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov @Override 211551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void onPostExecute(Void result) { 211651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).commit(); 211751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(savedProviderStatus); 2118f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 2119f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // Recursive invocation, needed to cover the case where locale 2120f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // changes once and then changes again before the db upgrade is completed. 2121f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov verifyLocale(); 212251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 212351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov }; 212451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 212551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov task.execute(providerStatus); 212651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 212751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 212831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 2129de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 2130b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 2131b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 213231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 213331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 2134013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 2135013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 2136013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 2137013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 21385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 213972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public ContactDirectoryManager getContactDirectoryManager() { 214072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return mContactDirectoryManager; 214172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 214272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 214372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 21445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 21455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 21465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 21475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 214872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 214972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov protected void startContactDirectoryManager() { 215072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov getContactDirectoryManager().start(); 215172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 215272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 21533d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 2154b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 2155b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 21563d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 21573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2158568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 2159568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 2160568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2161568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2162568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 2163568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 2164568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 2165568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 2166568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 2167bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 2168bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 2169bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (mAccessLatch == null) { 2170bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 2171bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2172568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2173568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 2174568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2175568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 217680952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov final SharedPreferences prefs = 217780952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov PreferenceManager.getDefaultSharedPreferences(getContext()); 217880952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov mDbHelper.setLocale(ContactsProvider2.this, mCurrentLocale); 217980952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 218080952e03e425a04ea2fd77e3ff44a8453ffdefe1Dmitri Plotnikov 2181bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 2182bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importLegacyContacts(importer)) { 2183bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov onLegacyContactImportSuccess(); 2184bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2185bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov onLegacyContactImportFailure(); 2186568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2187568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2188568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 2189568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2190568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 2191568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2192568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2193bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 2194bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 2195bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 2196bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 2197bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 2198bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 2199bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 2200bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2201b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 2202b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDbHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 2203b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 2204bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 2205bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch.countDown(); 2206bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch = null; 2207bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 2208bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2209bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2210bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 2211bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 2212bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 2213bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 2214bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 2215bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 2216bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 2217bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2218bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 2219bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 2220bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 2221bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 2222bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 2223bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 2224bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 2225bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 2226bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 2227bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2228bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 2229bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2230bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 2231bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 22323d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 22333d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 22343d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 2235568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 22360e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 22373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 22383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 2239bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 2240bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2241bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 2242bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 2243bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 2244bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 22453d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 22463d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 22473d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 2248bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 2249bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 22503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 22513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2252a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 2253a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 2254a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 2255a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 2256b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 2257a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 2258a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2259568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 2260568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 2261568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 2262568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 2263568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 2264568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 2265568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 2266568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 2267ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 2268ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 2269ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 2270ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 2271ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 2272ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 2273ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 2274ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 227581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 2276ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2277ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2278568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2279568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2280568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2281568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2282568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 2283568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2284568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 2285568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2286568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2287568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2288568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 2289bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (mAccessLatch != null) { 2290bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 2291bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 2292bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 2293bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 2294bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (match == PROVIDER_STATUS && isLegacyContactImportNeeded()) { 2295bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 2296bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 2297bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov importLegacyContactsAsync(); 2298bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 2299bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2300bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 2301bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2302bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2303bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2304568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2305568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 2306568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2307568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2308568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2309568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 2310568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2311568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 2312568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2313568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2314568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2315568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2316568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 2317568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2318568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 2319568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2320568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 23214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2322285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 2323bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2324b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 2325b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2326285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 23271ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 2328b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2329b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2330b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2331b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 2332285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 2333b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 2334df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 2335a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.clear(); 2336285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2337285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2338285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2339285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 23401129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 2341bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2342b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2343b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2344285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 2345b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 23461ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 23471a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 23481a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 2349b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 23501a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 2351b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2352b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2353b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2354bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2355b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2356b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 23571129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 235808e42c9c153a60bf2e7c71dd40bf84bb5fc93555Dmitri Plotnikov for (long rawContactId : mInsertedRawContacts.keySet()) { 2359d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(mDb, rawContactId); 2360d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mContactAggregator.onRawContactInsert(mDb, rawContactId); 2361285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2362b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2363a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov if (!mDirtyRawContacts.isEmpty()) { 2364a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2365a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2366a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mDirtyRawContacts); 2367a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2368a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2369a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2370a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2371b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 2372a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2373a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2374a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mUpdatedRawContacts); 2375a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2376a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2377b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2378b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2379b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 2380b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 23819d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana if (mDbHelper.getSyncState().update(mDb, id, entry.getValue()) <= 0) { 23829d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 23839d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 23849d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 2385b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2386b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2387b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2388b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2389b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2390a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2391a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2392a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2393a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2394a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private void appendIds(StringBuilder sb, HashSet<Long> ids) { 2395b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2396a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2397b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2398a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2399a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2400285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2401285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2402285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2403cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 240481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 240581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 240681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 240781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 240881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 240981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 241081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2411cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2412568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 241351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 241451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mProviderStatus = status; 241551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.ProviderStatus.CONTENT_URI, 241651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov null, false); 241751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 241851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2419285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 2420ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return mInsertedRawContacts.containsKey(rawContactId); 2421285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2422285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 24233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 24243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 24253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 24263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 24273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 24283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 24293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 24303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 24313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 24324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2433de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2434bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 24351129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2436b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2437f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2438f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2439f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2440f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2441a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2442a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 244335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2444a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 244535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2446b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 244735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 244835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2449d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2450d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 24516bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 24526bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 24536bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 24545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2455dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana id = insertRawContact(uri, values, callerIsSyncAdapter); 2456f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2457a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2458a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2459a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 24615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2462f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2463f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2464a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2465a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2466a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2467a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2468f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2469f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2470a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2471a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2472a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2473ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2474f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2475f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2476ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2477ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2478ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2479eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 24805aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 248143880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2482eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2483eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2484eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 248582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 248682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 24871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 24881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24891f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2490a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 249181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2492f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2493a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2494a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 24967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 24977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2499de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2500a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2501a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2502a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2503e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2504e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2505e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2506e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2507e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2508e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2509e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2510e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2511e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2512e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2513e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2514e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2515e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 25167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2517e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2518f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2519f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2520e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2521f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2522f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2523f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2524e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2525e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2526e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2527e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2528e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 2529fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2530fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 2531e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2532e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2533e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2534e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2535e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2536e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2537e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2538e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2539e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2540e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2541e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2542e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 2543fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2544fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 2545e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2546e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2547e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2548f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2549f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2550e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2551f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2552f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2553e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2554e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2555f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2556f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2557e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2558f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2559f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2560f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2561f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2562035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2563f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2564e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 25657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2568d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 25696bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 25706bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 25716bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 25726bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2573d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2574de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 25756bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 25766bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 25776bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2578a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2579a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2580f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2581f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2582dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param callerIsSyncAdapter 2583a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2584a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2585dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private long insertRawContact(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2586f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2587f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2588f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2589f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2590e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 25917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25923d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 25933d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2594f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 25953d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 25963d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2597f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 2598f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 2599f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 2600f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 2601f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2602f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId, aggregationMode); 2603285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2604285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2605e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mInsertedRawContacts.put(rawContactId, account); 2606f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2607dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 2608dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 2609dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long starred = values.getAsLong(RawContacts.STARRED); 2610dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (starred != null && starred != 0) { 2611dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred != 0); 2612dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2613dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2614dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2615023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2616a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2617a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2618dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void addAutoAddMembership(long rawContactId) { 2619dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID, 2620dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2621dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2622dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2623dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2624dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2625dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2626dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private Long findGroupByRawContactId(String selection, long rawContactId) { 2627dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.GROUPS + "," + Tables.RAW_CONTACTS, PROJECTION_GROUP_ID, 2628dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, 2629dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}, 2630dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana null /* groupBy */, null /* having */, null /* orderBy */); 2631dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 2632dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 2633dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return c.getLong(0); 2634dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2635dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return null; 2636dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2637dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 2638dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2639dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2640dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2641dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateFavoritesMembership(long rawContactId, boolean isStarred) { 2642dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID, 2643dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2644dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2645dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (isStarred) { 2646dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2647dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2648dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana deleteDataGroupMembership(rawContactId, groupId); 2649dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2650dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2651dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2652dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2653dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void insertDataGroupMembership(long rawContactId, long groupId) { 2654dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues groupMembershipValues = new ContentValues(); 2655dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.GROUP_ROW_ID, groupId); 2656dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 2657dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(DataColumns.MIMETYPE_ID, 2658dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDbHelper.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 2659dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.insert(Tables.DATA, null, groupMembershipValues); 2660dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2661dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2662dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void deleteDataGroupMembership(long rawContactId, long groupId) { 2663dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final String[] selectionArgs = { 2664dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(mDbHelper.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)), 2665dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(groupId), 2666dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(rawContactId)}; 2667dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs); 2668dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2669dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2670a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2671a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2672a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2673a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2674a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2675a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2676f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2677a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2678de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2679de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 268067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2681de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 268220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2683de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2684de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2685de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2686b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2687de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2688de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2689508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2690de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2691de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2692de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2693de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2694de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 26954097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2696b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2697de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2698a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2699a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2700a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2701f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2702de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2703a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2704b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2705a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 27064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 27088e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 27098e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 27108e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 27118e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 27128e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2713b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2714f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 27158e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 27168e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 27178e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 27188e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 271969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode, false); 2720f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 27218e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 27228e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 27238e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2724b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2725f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 27268e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 27278e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 27288e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2729f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 27308e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2731f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2732c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 2733b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 27348e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2735f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 27368e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2737f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2738f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2739f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2740a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 27415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 27429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 27439261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 27445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 27459261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 27469261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 27479261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 27489261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 27499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 2750ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId, 2751ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Account account) { 2752ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2753ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (account == null) { 27544da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 2755ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 27564da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov RawContacts._ID + "=?", mSelectionArgs1, null, null, null); 2757ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov try { 2758ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2759ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = c.getString(RawContactsQuery.ACCOUNT_NAME); 2760ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = c.getString(RawContactsQuery.ACCOUNT_TYPE); 2761ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 2762ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov account = new Account(accountName, accountType); 2763ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 27649261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2765ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } finally { 2766ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov c.close(); 27679261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 27689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2769ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 27709261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 27719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 2772ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov + "has a sourceid the the contact must be associated with " 27739261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 27749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 27759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2776ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ArrayList<GroupIdCacheEntry> entries = mGroupIdCache.get(sourceId); 2777ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entries == null) { 2778ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries = new ArrayList<GroupIdCacheEntry>(1); 2779ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.put(sourceId, entries); 2780ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2781ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2782ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int count = entries.size(); 2783ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov for (int i = 0; i < count; i++) { 2784ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = entries.get(i); 2785ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entry.accountName.equals(account.name) && entry.accountType.equals(account.type)) { 2786ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 2787ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2788ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2789ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2790ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = new GroupIdCacheEntry(); 2791ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountName = account.name; 2792ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountType = account.type; 2793ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.sourceId = sourceId; 2794ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries.add(0, entry); 2795ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 27969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 27975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 2798ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 27999261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2800df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 28019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 2802ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2803ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = c.getLong(0); 28049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 28059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2806df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2807df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 28089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 28099261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 28109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 28119261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 28129261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 28139261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2814ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = groupId; 28159261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 28169261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 28179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 28189261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2819ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2820ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 28219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 28229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2823d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private interface DisplayNameQuery { 28241129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov public static final String RAW_SQL = 28251129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov "SELECT " 28261129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + DataColumns.MIMETYPE_ID + "," 28271129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.IS_PRIMARY + "," 28281129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.DATA1 + "," 28295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA2 + "," 28305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA3 + "," 28315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA4 + "," 28325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA5 + "," 28335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA6 + "," 28345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA7 + "," 28355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA8 + "," 28365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA9 + "," 28375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA10 + "," 28385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA11 + 28391129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " FROM " + Tables.DATA + 28401129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " WHERE " + Data.RAW_CONTACT_ID + "=?" + 28411129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " AND (" + Data.DATA1 + " NOT NULL OR " + 28421129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Organization.TITLE + " NOT NULL)"; 2843d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2844d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int MIMETYPE = 0; 2845d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int IS_PRIMARY = 1; 28465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int DATA1 = 2; 28475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int GIVEN_NAME = 3; // data2 28485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FAMILY_NAME = 4; // data3 28495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PREFIX = 5; // data4 28505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int TITLE = 5; // data4 28515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int MIDDLE_NAME = 6; // data5 28525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int SUFFIX = 7; // data6 28535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_GIVEN_NAME = 8; // data7 28545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_MIDDLE_NAME = 9; // data8 28555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME = 9; // data8 28565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_FAMILY_NAME = 10; // data9 28575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FULL_NAME_STYLE = 11; // data10 28585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME_STYLE = 11; // data10 28595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_NAME_STYLE = 12; // data11 2860d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2861d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2862d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov /** 2863d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * Updates a raw contact display name based on data rows, e.g. structured name, 2864d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * organization, email etc. 2865d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov */ 2866ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 2867bca1c8b44f99528fc123d5547723e44771e8e934Mike Lockwood int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 28685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name bestName = null; 28695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestDisplayName = null; 28705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestPhoneticName = null; 28715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 2872d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 28731129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 28741129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Cursor c = db.rawQuery(DisplayNameQuery.RAW_SQL, mSelectionArgs1); 2875d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov try { 2876d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov while (c.moveToNext()) { 28771129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov int mimeType = c.getInt(DisplayNameQuery.MIMETYPE); 28785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int source = getDisplayNameSource(mimeType); 28795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source < bestDisplayNameSource || source == DisplayNameSources.UNDEFINED) { 28805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 28815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28821129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 28835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source == bestDisplayNameSource && c.getInt(DisplayNameQuery.IS_PRIMARY) == 0) { 28845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 2885d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 28861129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 28875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mimeType == mMimeTypeIdStructuredName) { 28885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name name; 28895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestName != null) { 28905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = new NameSplitter.Name(); 28915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 28925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = mName; 28935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.clear(); 28945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 28955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.prefix = c.getString(DisplayNameQuery.PREFIX); 28965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.givenNames = c.getString(DisplayNameQuery.GIVEN_NAME); 28975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.middleName = c.getString(DisplayNameQuery.MIDDLE_NAME); 28985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.familyName = c.getString(DisplayNameQuery.FAMILY_NAME); 28995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.suffix = c.getString(DisplayNameQuery.SUFFIX); 29005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.fullNameStyle = c.isNull(DisplayNameQuery.FULL_NAME_STYLE) 29015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? FullNameStyle.UNDEFINED 29025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.FULL_NAME_STYLE); 29035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticFamilyName = c.getString(DisplayNameQuery.PHONETIC_FAMILY_NAME); 29045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticMiddleName = c.getString(DisplayNameQuery.PHONETIC_MIDDLE_NAME); 29055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticGivenName = c.getString(DisplayNameQuery.PHONETIC_GIVEN_NAME); 29065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticNameStyle = c.isNull(DisplayNameQuery.PHONETIC_NAME_STYLE) 29075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 29085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.PHONETIC_NAME_STYLE); 29095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (!name.isEmpty()) { 29105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 29115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName = name; 29125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else if (mimeType == mMimeTypeIdOrganization) { 29145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 29155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 29165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 2917d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov bestDisplayNameSource = source; 29181129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 29191129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 29205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = c.getString(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME); 29215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = 29225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.isNull(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE) 29235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 29245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE); 29255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 29265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.TITLE, mCharArrayBuffer); 29275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 29281129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayNameSource = source; 29291129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 29301129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 29315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 29325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 29331129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 2934d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 29355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 29365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Display name is at DATA1 in all other types. 29375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // This is ensured in the constructor. 29385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 29405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 29415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 29425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 29435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 29445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 29455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 29465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 29475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 2948d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2949d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2950d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2951d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } finally { 2952d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov c.close(); 2953d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2954d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 29555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary; 29565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNameAlternative; 29575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyPrimary = null; 29585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyAlternative = null; 29595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int displayNameStyle = FullNameStyle.UNDEFINED; 29605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestDisplayNameSource == DisplayNameSources.STRUCTURED_NAME) { 29625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = bestName.fullNameStyle; 29635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.CJK 29645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.UNDEFINED) { 29655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 29665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName.fullNameStyle = displayNameStyle; 29675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = mNameSplitter.join(bestName, true); 29705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative = mNameSplitter.join(bestName, false); 29715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = mNameSplitter.joinPhoneticName(bestName); 29735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = bestName.phoneticNameStyle; 29745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 29755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = displayNameAlternative = bestDisplayName; 29765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticName != null) { 29795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = bestPhoneticName; 29805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticNameStyle == PhoneticNameStyle.UNDEFINED) { 29815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = mNameSplitter.guessPhoneticNameStyle(bestPhoneticName); 29825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 29845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED) { 29855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.guessFullNameStyle(bestDisplayName); 29865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED 29875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.CJK) { 29885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedNameStyleBasedOnPhoneticNameStyle( 29895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle, bestPhoneticNameStyle); 29905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 29925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 2993ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao if (displayNameStyle == FullNameStyle.CHINESE || 2994ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao displayNameStyle == FullNameStyle.CJK) { 29955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = 2996cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().getSortKey( 2997ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao displayNamePrimary, displayNameStyle); 29985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 30005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 30015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (sortKeyPrimary == null) { 30025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = displayNamePrimary; 30035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyAlternative = displayNameAlternative; 30045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 30055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 30065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov setDisplayName(rawContactId, bestDisplayNameSource, displayNamePrimary, 30075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative, bestPhoneticName, bestPhoneticNameStyle, 30085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary, sortKeyAlternative); 3009d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 3010d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 30111129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private int getDisplayNameSource(int mimeTypeId) { 30121129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (mimeTypeId == mMimeTypeIdStructuredName) { 30131129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.STRUCTURED_NAME; 30141129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdEmail) { 30151129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.EMAIL; 30161129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdPhone) { 30171129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.PHONE; 30181129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdOrganization) { 30191129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.ORGANIZATION; 30201129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdNickname) { 30211129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.NICKNAME; 30221129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else { 30231129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.UNDEFINED; 30241129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 30251129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 30261129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 30279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 302820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 302920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 3030f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 303120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 303220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3033de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3034de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 303514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 3036de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 3037de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 303814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 303914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 3040a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3041a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 3042f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 304388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 304488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 304520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 304620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 3047de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 304820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 304920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 305020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 305120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 305220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 305388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 305488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 305588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 305620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 3057f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 305888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 305988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 30604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 30614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=?", 30624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 3063f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 306420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 306520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 306620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 306720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 306820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 306914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 307020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 307120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 307220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 307320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 307420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 307520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 307620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 307720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 307820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 30797a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 308020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 308120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 308220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3083a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3084813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return rowHandler.delete(mDb, c); 308520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 308620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 308720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 308820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 308920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 309020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 3091ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 3092ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 3093f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 3094f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 3095f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 3096f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 3097e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 3098ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3099ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 3100f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 310167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 3102f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 310367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 3104f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 3105ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3106dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final boolean isFavoritesGroup = mValues.getAsLong(Groups.FAVORITES) != null 3107dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ? mValues.getAsLong(Groups.FAVORITES) != 0 3108dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana : false; 3109dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3110f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 3111f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 311273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 311373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3114f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 3115ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3116dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && isFavoritesGroup) { 3117dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // add all starred raw contacts to this group 3118dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String selection; 3119dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs; 3120dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (account == null) { 3121dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + " IS NULL AND " 3122dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContacts.ACCOUNT_TYPE + " IS NULL"; 3123dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = null; 3124dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 3125dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + "=? AND " 3126dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContacts.ACCOUNT_TYPE + "=?"; 3127dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = new String[]{account.name, account.type}; 3128dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3129dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, 3130dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{RawContacts._ID, RawContacts.STARRED}, 3131dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, selectionArgs, null, null, null); 3132892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov try { 3133892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov while (c.moveToNext()) { 3134892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (c.getLong(1) != 0) { 3135892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov final long rawContactId = c.getLong(0); 3136892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov insertDataGroupMembership(rawContactId, result); 3137892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov setRawContactDirty(rawContactId); 3138892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 3139dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3140892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } finally { 3141892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov c.close(); 3142dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3143dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3144dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3145f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 31461a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3147ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 3148ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3149ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 3150ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3151ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31525aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 3153e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 31545aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 31551a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 31561a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3157e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 31581a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 3159e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 3160e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3161e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3162ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 316382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 31641f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 316582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 316682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 31670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 31684dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 31694dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 31700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 317182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 31724dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 31734dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 31744dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 31754dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 31761f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31771f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3178dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 3179dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 318082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 3181f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 31822526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 3183dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 3184dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 3185dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31862526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 31872526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 31881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 3189dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 3190dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 31920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 31930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 31940a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3195dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 3196dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 3197dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31982526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov String mimeTypeIdIm = String.valueOf(mMimeTypeIdIm); 3199dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 32002526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov String mimeTypeIdEmail = String.valueOf(mMimeTypeIdEmail); 3201f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3202f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 3203f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 3204f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 3205f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3206f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 3207f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 32082526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 32092526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 32102526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 32112526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 32122526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32132526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 32142526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32152526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 3216dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32172526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32182526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3219dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32202526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 32212526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 3222dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 32232526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 32242526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 32252526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 32262526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32272526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 32282526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 3229dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32302526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32312526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3232dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 3233dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32341f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 323582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 32362526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 32372526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 3238dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 323970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 3240f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 324170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 32421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 32431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 3244de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 32452526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 32464394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID); 32471f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 324867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 32495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 3250e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 32511f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 32521f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 32531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 32541f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32551f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 325631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 325731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 325831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 32591f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 326182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 3262a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 3263a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 3264a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 3265a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 3266a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3267a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3268a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 326982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 3270a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 3271a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 327282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 327382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 327482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 327582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 327682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 3277a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 327882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 327982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 3280aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori mValues.put(StatusUpdates.CHAT_CAPABILITY, 3281aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori values.getAsString(StatusUpdates.CHAT_CAPABILITY)); 32821f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3283a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 3284a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 3285a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3286e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 32870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 328882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 328982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 32900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 32910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 32920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 32930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 32940a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 32950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 32960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 32970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 32980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 32990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 33000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 33010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3302a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 3303a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 3304a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 330582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 330682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 3307a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 3308a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 33095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 3, status); 33105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 4, resPackage); 33115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 5, iconResource); 33125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 6, labelResource); 3313a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 3314a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 3315a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3316a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 3317a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 33185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 2, status); 33195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 3, resPackage); 33205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 4, iconResource); 33215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 5, labelResource); 3322a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 3323a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 3324a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 33250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 3326a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 33275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 2, status); 3328a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 33295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 4, status); 3330a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 33310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusAttributionUpdate, 1, resPackage); 33335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 2, iconResource); 33345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 3, labelResource); 33350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 33360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 3337a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3338e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3339e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3340bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3341a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 3342a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 3343a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 3344a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 3345a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3346a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3347a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 33481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 33491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 33504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3351de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 3352bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3353b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 3354b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3355b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3356f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3357f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 3358508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 3359508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 336035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3361b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 336235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3363b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 3364b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3365b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3366b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3367b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 3368b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3369cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 3370cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 3371cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 3372cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3373cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3374d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3375d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3376dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 33776bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 33786bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 33799fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 33802e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 33812e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 33822e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3383fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3384fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 33852e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 33862e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 33872e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 3388dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 33892e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 33902e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 33919fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 33929fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 33939fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 33949fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 33959fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 33969fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 3397a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 33989fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 33999fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 34009fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 34019fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34029fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 34039fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 34049fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34059fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 340660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 34079fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 34089fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 34099fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann Cursor c = query(db, lookupQb, null, selection, args, null, null, null); 34109fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 34119fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 34129fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 3413dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34149fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34159fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 34169fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 34179fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 34189fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34199fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 34209fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 34219fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34229fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34239fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 34242971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 34252971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 3426fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, 3427fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 3428e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 34292971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 34302971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 34312971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 3432fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 3433fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 3434fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 34352971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34362971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 34372971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 34382971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34392971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 34402971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34412971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 34425ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 34432971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 3444fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return deleteRawContact(rawContactId, mDbHelper.getContactId(rawContactId), 3445fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 3446508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3447508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 344820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3449f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 3450944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 3451f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 345220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 345320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 345448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 345548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 345648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 345748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3458508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3459f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 34604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 34614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 3462ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3463ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3464ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3465f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 34665aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 34672971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34682971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 34692971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 34702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 34712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 3472e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 34732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 34742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 34755aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 34762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34772971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 34782971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 34792971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 348081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3481f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 348281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 34832971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3484508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3485508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3486eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 348743880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3488e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3489eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3490eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 349182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 34920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 34931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 34941f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 349581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 349681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 34973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 349881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3499508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 35004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35021c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3503ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3504b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 350594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 3506de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 350794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 350894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 350994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 351094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3511f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 3512de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 351394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 351494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 351594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3516f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 3517de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 351894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 351994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 35201a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 352194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 352294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 352394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 35245aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 3525e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 35261a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3527e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3528e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3529e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3530dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int deleteContact(long contactId, boolean callerIsSyncAdapter) { 353196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 3532cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 353396b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 353496b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 3535cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3536cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3537cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3538dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 3539cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3540cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3541cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3542cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3543cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3544cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3545cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3546cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3547fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 35483389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3549f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 355014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 3551fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov int count = mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 3552fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForContact(mDb, contactId); 3553fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 355433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 3555b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 3556dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 355733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 355833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 355933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 35600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 35619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 35629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 35639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 35649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 35659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 35669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 35679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 35689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 35690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 35700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3571dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) { 357281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 357381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3574cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3575cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3576cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3577cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3578cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3579cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3580dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues, callerIsSyncAdapter); 3581cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3582cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 35834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3584de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3585de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3586bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3587b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3588b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3589b5a4add17815167d20a90645779df34cdf45280dFred Quintana 359035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 359100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 359200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3593b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3594b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 35951129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 3596b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 3597b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3598b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3599b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3600f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3601f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 360200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 360335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3604b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3605b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3606b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3607b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3608b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3609b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3610b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3611b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3612b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3613b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3614b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 361535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3616d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3617dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 361800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 361900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 362000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3621d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3622dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter); 3623c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3624c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3625c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 36262e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 36272e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 36282e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 36292e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 36302e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3631fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3632fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 36332e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 36342e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 36352e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 3636dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(contactId, values, callerIsSyncAdapter); 36372e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 36382e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 36392e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 36407d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 36417d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 36427d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 36437d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 36447d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 36457d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 36467d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 36477d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 36487d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 36497d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 365020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3651944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3652f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 365381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3654f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 365581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 365620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 365720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3658c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 365948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 366048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 366148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 366248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3663f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 366481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3665f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 366681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 366700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 366800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 36697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 36705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 36715ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 3672dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, selection, selectionArgs, callerIsSyncAdapter); 36737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 36747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 36757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 36765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 367733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 36784529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 36794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 36804da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 3681dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND(" + selection + ")", selectionArgs, 3682dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 36834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 36844da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 3685dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1, 3686dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 36874529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 36887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 36897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 36907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3691ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 36925aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3693f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 369481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3695f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 369681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3697ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3698ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3699ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3700ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3701ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 37024da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 37034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 370473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 37055aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 37065aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 370781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3708f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 370981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3710ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3711ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3712ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3713127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 3714de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 3715b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3716b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3717b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3718eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3719e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3720e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 372143880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3722eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3723eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3724eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 37259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 37269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 37279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 37289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37299705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 373072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case DIRECTORIES: { 373172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager.scheduleDirectoryUpdateForCaller(); 373272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov count = 1; 3733d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 3734d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3735d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 373681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 373781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 3738f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 373981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 374000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 374100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 374200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 37434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 37459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 37469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 37479705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 37489705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 37499705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 37509705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 37519705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 37529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 37539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 37549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 37559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 37569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 37589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 37599705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 37609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 37619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 37629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 37639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 37659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 37669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 37679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 37699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 37709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 37719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 37729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 37739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 37749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 37759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 37769705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 37779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 37789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 37809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 37819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 37829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 37839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 37849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 37859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 37869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 37879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 37889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 37899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 37909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 37919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 37929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 37939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 37959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 37969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 37979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 37989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 3799aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.CHAT_CAPABILITY, values, 3800aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori StatusUpdates.CHAT_CAPABILITY); 38019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 38029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 38039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 38045aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 3805f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 380673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3807ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3808ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 380973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 3810f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 381173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 381273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 381373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 381473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 381573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 381673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 381773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 381873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3819ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 38201a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 38211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 382294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 38236ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 38241129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 38256ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 3826e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 38276ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 38286ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 38296ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 38306ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 38316ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 38326ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 38336ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 38346ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 38356ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 3836ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 38376ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 38386ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 38396ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 38406ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 38416ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 38426ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 38436ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 38446ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 384594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 384694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 384794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 3848b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 3849b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 3850e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 38511a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 38521a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3853e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3854e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3855e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3856e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3857dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs, 3858dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 38594529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 38604529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 38614529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 38624529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 386373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 386497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 386597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 386697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0"); 386797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 386897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 38694529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3870b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 387151bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 38724529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 38734529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 38744529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 38754529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 3876dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContact(rawContactId, values, callerIsSyncAdapter); 38774529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 38784529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 38794529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 38804529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 38814529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 38824529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 38834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 38844529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 38854529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 3886dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContact(long rawContactId, ContentValues values, 3887dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 388896b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 388996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 389019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 389119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 389219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 3893ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 3894ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 389519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 389619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 389796b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1, null, null, null); 389819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 389919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 390019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 3901ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 3902ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 390319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 390419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 390519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 390619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 390719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 390819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 390919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 3910f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 391196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker int count = mDb.update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 39125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3913f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 3914f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 3915f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 3916f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 3917f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 3918f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 391969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode, false); 3920f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 3921f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 3922433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 3923dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 3924dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 3925dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana values.getAsLong(RawContacts.STARRED) != 0); 3926dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 39274529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3928dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 3929dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then update the 3930dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // favorites group membership based on whether or not this contact is starred. 3931dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // If it is starred, add a group membership, if one doesn't already exist 3932dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // otherwise delete any matching group memberships. 3933dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 3934dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean starred = 0 != DatabaseUtils.longForQuery(mDb, 3935dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SELECTION_STARRED_FROM_RAW_CONTACTS, 3936dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}); 3937dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred); 3938dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3939dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3940dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3941dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then add a 3942dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // group membership to the group marked as AutoAdd, if any. 3943dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 3944dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 3945433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3946dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3947285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 39482b7a632bba423357ae5641f94da6a2f71afc523bDmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(mDb, rawContactId); 3949285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 3950f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 3951f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 3952f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 3953f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 3954f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 3955f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(1, rawContactId); 3956f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(2, rawContactId); 3957f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.execute(); 3958f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 3959f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(mDb, rawContactId); 3960f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 396119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 396219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 3963ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.put(rawContactId, new Account(accountName, accountType)); 396419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 39655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 396733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 396833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3969321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3970f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 397120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 397220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 397320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 39745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 397520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 397620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 397720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 397820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 397920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3980b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 398120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 398220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 398370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 398470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 398520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 398620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 398720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 398870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 398920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 399070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 399120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 399270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 399320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 399470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 399520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 399620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 399797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 399897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 399997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov Data.IS_READ_ONLY + "=0"); 400097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 400197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 4002653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 400320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4004653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 4005653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 400614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 4007653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 4008653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 4009f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 401020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 4011653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 4012653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 401320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 401420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4015653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 401620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 401720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4018f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 4019653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 4020653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 4021321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4022653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 402314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 4024a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 4025813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (rowHandler.update(mDb, values, c, callerIsSyncAdapter)) { 4026813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 1; 4027813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } else { 4028813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 0; 4029a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 4030321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4031321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 40328c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 4033dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 40348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 4035b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 40368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 40378c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 40388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 40398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 40408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 4041dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateContactOptions(contactId, values, callerIsSyncAdapter); 40428c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 40438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 40448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 40458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 40468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 40478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 40488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 40498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 40508c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4051dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateContactOptions(long contactId, ContentValues values, 4052dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 4053d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 40548c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4055b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 4056d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4057b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 4058d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4059b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 4060d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4061b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 4062d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4063b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 4064d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 4065d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4066d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 40678c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 4068d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 4069d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 4070d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 40718c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 4072c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 40738c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 4074c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 4075c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 40764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 407797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?" 407897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov + " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1); 40798c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4080dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) { 4081dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 4082dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?", 4083dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null, null, null); 4084dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 4085dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (cursor.moveToNext()) { 4086dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long rawContactId = cursor.getLong(0); 4087dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4088dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.getAsLong(RawContacts.STARRED) != 0); 4089dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4090dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 4091dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana cursor.close(); 4092dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4093dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4094dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 40958c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 40968c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 40978c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4098b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 40998c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4100b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 41018c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4102b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 41038c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4104b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 41058c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4106b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 41078c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 41088c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 41099b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori int rslt = mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 41106e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 41119b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 41129b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 41139b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 41149b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 41159b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 41169b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 4117f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 4118d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4119127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 4120127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 41210c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 41220c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 412380c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 41240c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 41250c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 41260c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 41270c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 41280c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 41290c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 41300c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 4131b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4132127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 41330c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 41344da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 41354da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 41360c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 41374da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 41384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 41390c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 41406bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 41416bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 41420c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 41430c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 41440c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 41450c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 4146127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 4147127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 41483389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 414969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1, 415069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 415169cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2, 415269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 4153dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 4154b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 41550c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 41560c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 4157b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId2 = mDbHelper.getContactId(rawContactId2); 41580c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 4159127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 4160127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 4161127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 4162127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 4163b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4164b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 416570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 4166f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 4167e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov boolean accountsChanged = false; 4168627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 416970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 417070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 4171dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana findValidAccounts(existingAccounts); 4172743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 4173743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // Add a row to the ACCOUNTS table for each new account 4174743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 4175743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov if (!existingAccounts.contains(account)) { 4176e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 4177743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 4178743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov + ", " + RawContacts.ACCOUNT_TYPE + ") VALUES (?, ?)", 4179743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov new String[] {account.name, account.type}); 4180743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 4181743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 418248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 4183627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 4184743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // in the accountsToDelete set will be extra accounts whose data must be deleted. 4185627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 4186627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 4187627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 418870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 418970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 419033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov if (!accountsToDelete.isEmpty()) { 4191e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 4192e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov for (Account account : accountsToDelete) { 4193e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov Log.d(TAG, "removing data for removed account " + account); 4194e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 4195e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 4196e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 4197e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 4198e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 4199e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 4200e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 4201e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 4202e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "SELECT " + RawContacts._ID + 4203e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4204e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4205e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 4206e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 4207e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 4208e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4209e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 4210e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 4211e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 4212e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 4213e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 4214e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 4215e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 4216e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 4217e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + "=?", params); 4218d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mDb.execSQL( 4219d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov "DELETE FROM " + Tables.DIRECTORIES + 4220d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " WHERE " + Directory.ACCOUNT_NAME + "=?" + 4221d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " AND " + Directory.ACCOUNT_TYPE + "=?", params); 4222d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mDirectoryCache = null; 4223e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 4224e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 422533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 422633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 4227e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov // names or photos. If so, fix up those contacts. 422833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 422933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Cursor cursor = mDb.rawQuery("SELECT " + Contacts._ID + 423033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 423133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 423269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 423369cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 423469cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 423533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 423633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 423769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 423869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 423933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 424033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 424133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 424233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 424333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 424433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 424533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 424633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 424733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 424833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 424933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 4250e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDbHelper.updateAllVisible(); 425133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 425233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 4253e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (accountsChanged) { 4254e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 4255e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 425670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 425770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 425870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 425970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 426073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 426170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4262619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 426372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPackageChanged(String packageName) { 426472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager.onPackageChanged(packageName); 4265d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4266d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4267619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 4268627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 4269627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 4270dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void findValidAccounts(Set<Account> validAccounts) { 4271743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov Cursor c = mDb.rawQuery( 4272743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "SELECT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 4273743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " FROM " + Tables.ACCOUNTS, null); 4274627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4275627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 4276dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!c.isNull(0) || !c.isNull(1)) { 4277627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 4278627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4279627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4280627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 4281627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 4282627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4283627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4284627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4285627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov /** 4286622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 4287622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 428867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 428967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 429067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 429167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 429267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 429367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 429467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 429567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 429667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 429767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 429867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 429967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 4300dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 4301622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 4302dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 4303dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 4304622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4305622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4306dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 4307622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4308622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 43094f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 43104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 43114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 4312d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY); 4313d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directory == null || directory.equals("0")) { 4314d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return queryLocal(uri, projection, selection, selectionArgs, sortOrder, false); 4315d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } else if (directory.equals("1")) { 4316d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return queryLocal(uri, projection, selection, selectionArgs, sortOrder, true); 4317d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4318d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4319d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryInfo directoryInfo = getDirectoryAuthority(directory); 4320d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo == null) { 4321d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov throw new IllegalArgumentException( 4322d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mDbHelper.exceptionMessage("Invalid directory ID", uri)); 4323d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4324d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4325d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Builder builder = new Uri.Builder(); 4326d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.scheme(ContentResolver.SCHEME_CONTENT); 4327d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.authority(directoryInfo.authority); 4328d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.encodedPath(uri.getEncodedPath()); 4329d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountName != null) { 4330d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, directoryInfo.accountName); 4331d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4332d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountType != null) { 4333d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, directoryInfo.accountType); 4334d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4335d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Uri directoryUri = builder.build(); 433609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 433709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (projection == null) { 433809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov projection = getDefaultProjection(uri); 433909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 434009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 4341d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return getContext().getContentResolver().query(directoryUri, projection, selection, 4342d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs, sortOrder); 4343d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4344d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4345d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final class DirectoryQuery { 4346d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 4347d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory._ID, 4348d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.DIRECTORY_AUTHORITY, 4349d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_NAME, 4350d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_TYPE 4351d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov }; 4352d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4353d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int DIRECTORY_ID = 0; 4354d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int AUTHORITY = 1; 4355d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_NAME = 2; 4356d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_TYPE = 3; 4357d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4358d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4359d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 4360d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Reads and caches directory information for the database. 4361d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 4362d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private DirectoryInfo getDirectoryAuthority(String directoryId) { 4363d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (mDirectoryCache == null) { 4364d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mDirectoryCache = new HashMap<String, DirectoryInfo>(); 4365d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Cursor cursor = mDb.query(Tables.DIRECTORIES, 4366d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryQuery.COLUMNS, 4367d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov null, null, null, null, null); 4368d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov try { 4369d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov while (cursor.moveToNext()) { 4370d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryInfo info = new DirectoryInfo(); 4371d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String id = cursor.getString(DirectoryQuery.DIRECTORY_ID); 4372d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov info.authority = cursor.getString(DirectoryQuery.AUTHORITY); 4373d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov info.accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME); 4374d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov info.accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE); 4375d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mDirectoryCache.put(id, info); 4376d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4377d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } finally { 4378d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov cursor.close(); 4379d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4380d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4381d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4382d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return mDirectoryCache.get(directoryId); 4383d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4384d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 438572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void resetDirectoryCache() { 438672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mDirectoryCache = null; 438772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 438872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 4389d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public Cursor queryLocal(Uri uri, String[] projection, String selection, String[] selectionArgs, 4390d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String sortOrder, boolean hiddenOnly) { 4391bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 4392bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 4393bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 43940b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 4395b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 439635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4397d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 43981f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 4399c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 4400c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4401619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 4402619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 4403a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 44044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 440535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 4406b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 440735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 440835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4409d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 4410763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4411d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (hiddenOnly) { 4412d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Contacts.IN_VISIBLE_GROUP + "=0"); 4413d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4414619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 4415619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4416619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4417d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 44184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 4419763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 44204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 44214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 44226bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 44236bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 44246bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 44255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 44265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 44275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 44285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 44295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 4430fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4431fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 44325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 4433a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 44345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 44355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 44365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 44375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4438763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 4439a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4440a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 4441a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4442a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 4443a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 44445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 44455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4448763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 44494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 44504da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 44514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 44525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 44535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 44545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 44552149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_DATA: 44562149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_ID_DATA: { 44572149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 44582149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov int segmentCount = pathSegments.size(); 44592149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount < 4) { 44602149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 44612149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov "Missing a lookup key", uri)); 44622149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 44632149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String lookupKey = pathSegments.get(2); 44642149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount == 5) { 44652149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 44662149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 44672149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(lookupQb, uri, projection, false); 4468a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 4469a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 4470a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4471a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey); 4472a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 44732149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov return c; 44742149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 44752149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 44762149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov // TODO see if the contact exists but has no data rows (rare) 44772149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 44782149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 44792149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 44802149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 44812149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 44822149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov qb.appendWhere(" AND " + Data.CONTACT_ID + "=?"); 44832149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov break; 44842149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 44852149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 4486f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 4487f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 448842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 4489763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 4490f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 44914da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 44924da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 44934da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 4494f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 4495f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 4496f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 449742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 449842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 449942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 450042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return db.rawQuery( 450142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 450242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 450342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 450442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 450542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 450642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 4507ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 4508916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 4509ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 4510916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 4511ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4512916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet(qb, uri, projection, filterParam); 4513d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (hiddenOnly) { 4514d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Contacts.IN_VISIBLE_GROUP + "=0"); 4515d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4516ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4517ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4518ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4519ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 4520ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 45214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 4522ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 4523d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 45244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 45254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4526e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 45275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 45284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 45294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 45304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4531763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4532ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 45335e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 45345e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 45355e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 4536dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov starredProjection = 4537dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov appendProjectionArg(projection, TIMES_CONTACTED_SORT_COLUMN); 4538dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov frequentProjection = 4539dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov appendProjectionArg(projection, TIMES_CONTACTED_SORT_COLUMN); 45405e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 45415e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 45424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 45434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 45444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 4545d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 45465e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 45475e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 45484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 4549d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4550d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 4551d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 4552763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 45534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 45544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 4555d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 45565e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 45575e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 4558d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 4559d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 45604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 4561d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4562d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 4563d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 4564d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 45654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 45664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 4567d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 4568d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 4569d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4570d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 4571d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4572d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4573ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 4574763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4575b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 457671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 45774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 4578b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4579b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 4580b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4581b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 4582a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_DATA: { 45834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 458482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 45854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 45864da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 45876bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 45886bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 458900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 4590a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 45913653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 459282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 45934da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 45944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 45953653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 45963653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 45973653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 45983653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4599a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_ENTITIES: { 4600a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 4601a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 4602a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 4603a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 4604a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 4605a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4606a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4607a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ENTITIES: 4608a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ID_ENTITIES: { 4609a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 4610a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov int segmentCount = pathSegments.size(); 4611a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount < 4) { 4612a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4613a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov "Missing a lookup key", uri)); 4614a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4615a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lookupKey = pathSegments.get(2); 4616a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount == 5) { 4617a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 4618a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4619a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(lookupQb, uri, projection); 4620a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 4621a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4622a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 4623a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4624a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.CONTACT_ID, contactId, 4625a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.LOOKUP_KEY, lookupKey); 4626a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 4627a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 4628a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4629a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4630a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4631a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 4632a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 4633a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 4634a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?"); 4635a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 4636a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4637a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 46384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 463982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 464089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 46412815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 46422815f58f72f109790585931f601a63ddc02536a5Evan Millar } 46432815f58f72f109790585931f601a63ddc02536a5Evan Millar 464448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 464582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 46464da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 464748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 46484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 464948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 465048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 465148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 4652ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 465382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 465489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 4655ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 46564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 46574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4658a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 46595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 466045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 46615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 46625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 46635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 46645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 46657318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 46665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 466745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 46685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 46695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 4670892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filterParam); 4671892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (!TextUtils.isEmpty(number)) { 46725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 46735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 46745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 46755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 4676892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov " IN (SELECT DISTINCT " + PhoneLookupColumns.DATA_ID 4677892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 4678892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 4679892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append(number); 4680892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append("%')"); 468145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 468245d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 468345d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 468445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 468545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 468645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 468745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 46885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 46895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4690a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 4691ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 46925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 4693a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4694a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4695a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 4696ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4697ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4698ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 46994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 470082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 470189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 47024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 47034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 47044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 470548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 470682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 47074da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 47084da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 47094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 471048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 471148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 471248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 47135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 471482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 471589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 47164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 471708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 471808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String address = mDbHelper.extractAddressFromEmailAddress(email); 471908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 472008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 47214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 4722ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4723ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4724ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 47255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 472682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 472707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 472807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 472907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 473007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 473107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 473207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 473307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 47345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 473507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 473607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 473707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 473807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 473907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 474007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 474107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 474207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 474307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 474407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 474507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.DATA1 + " LIKE "); 474607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 474720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 474820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 474920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 475007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 475107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov /* 475207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * Using a UNION instead of an "OR" to make SQLite use the right 475307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * indexes. We need it to use the (mimetype,data1) index for the 475407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * email lookup (see above), but not for the name lookup. 475507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * SQLite is not smart enough to use the index on one side of an OR 475607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * but not on the other. Using two separate nested queries 475707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * and a UNION between them does the job. 475807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov */ 475907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 476007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " UNION SELECT " + Data._ID + 476107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 476207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 476307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN "); 47647318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 476520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 47665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 47675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4768a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 47695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 47705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 4771a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4772a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4773a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 47745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 47755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 47765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 4777ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 477882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 477989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 478089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 4781ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4782ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4783ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 478448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 478582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 47864da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 478748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 478848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 47894da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 479048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 479148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 479248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 47935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 4794763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 47954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 47964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 47985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 47995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 4800763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 48014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 48024da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 48034f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 48044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 48065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 48075ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 480882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 48094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 48104da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 4811e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4812e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4813e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 4814e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 481582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 4816e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4817e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4818e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 48194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 482082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 48214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 48224da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 4823a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 4824a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 4825a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 4826a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 48274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4828a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 4829a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 4830a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 4831892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sortOrder = " length(lookup.normalized_number) DESC"; 4832a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4833a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4834e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 4835892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String numberE164 = 4836892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.formatNumberToE164(number, getCurrentCountryIso()); 4837892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String normalizedNumber = 4838892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.normalizeNumber(number); 4839892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, normalizedNumber, numberE164); 4840e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 4841e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 4842e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 4843e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 4844a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 4845a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4846a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4847ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 4848b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4849ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 485089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4851ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4852ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4853ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4854ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 4855b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4856ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 48574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 48584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 4859ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4860ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4861ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4862ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 4863b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 4864ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 486589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 486689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 4867ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4868ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4869ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4870b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 48710c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 4872b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 4873b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 4874b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4875b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 487631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 4877d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 48782d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 48792d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 48802d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 48812d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 488231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 4883d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 4884d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 488531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 488631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 488731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 488831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 48895b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ArrayList<AggregationSuggestionParameter> parameters = null; 48905b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov List<String> query = uri.getQueryParameters("query"); 48915b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov if (query != null && !query.isEmpty()) { 48925b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters = new ArrayList<AggregationSuggestionParameter>(query.size()); 48935b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov for (String parameter : query) { 48945b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov int offset = parameter.indexOf(':'); 48955b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters.add(offset == -1 48965b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ? new AggregationSuggestionParameter( 489776dfa406e2cde19c824983c37fc92c1c5bf63eecDaniel Lehmann AggregationSuggestions.PARAMETER_MATCH_NAME, 48985b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter) 48995b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov : new AggregationSuggestionParameter( 49005b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(0, offset), 49015b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(offset + 1))); 49025b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 49035b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 49045b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 4905763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 49067581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 49077581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 49085b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov maxSuggestions, filter, parameters); 490931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 491031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4911eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 4912eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 4913eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 491489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4915e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4916e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 4917e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 4918b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 4919e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 492082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4921b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 4922e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4923e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 492482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4925b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 4926e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4927e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4928e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4929eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 4930eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 4931eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 493282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 49330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 49345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 49355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 49365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 493782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 49380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 49394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 49404da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 49415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 49425ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 49435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 4944c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 4945a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 4946c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4947c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4948c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 49492d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 49502d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill return mGlobalSearchSupport.handleSearchShortcutRefresh(db, lookupKey, projection); 4951c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4952c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 49531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 4954b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 49551b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 49561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 49571b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 49581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 4959b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 49601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 49611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 49621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 49631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 49641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 4965b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 49661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 49671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 49681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 49691b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 49701b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 4971b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 49721b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 497371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 49741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 49751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 49761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 497746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 4978a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 497946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 498046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 498146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 498246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 498346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 4984a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 49854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 49864da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 498746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 498846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 498946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 499009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 499109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 499209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 499309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 4994d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES : { 4995d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 4996d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 4997d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 4998d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4999d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 5000d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID : { 5001d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov long directoryId = ContentUris.parseId(uri); 5002d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5003d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5004d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(directoryId)); 5005d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Directory._ID + "=?"); 5006d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5007d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5008d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 50097a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov case COMPLETE_NAME: { 50107a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return completeName(uri, projection); 50117a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 50127a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 50134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 5014f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 5015c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 50164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 50174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 50187f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov qb.setStrictProjectionMap(true); 50197f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 5020ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 5021ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 5022ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 5023ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov cursor = bundleLetterCountExtras(cursor, db, qb, selection, selectionArgs, sortOrder); 5024ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5025ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 50265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 50295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 50305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 5031038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 5032038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 5033038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 5034038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 50355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 50365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 50374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 50384f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 50394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 50404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 50414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 50424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 504309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 504409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 504509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 504609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 504709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 504809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 504909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 505009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 505109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 505209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 505309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 505409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 505509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 505609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 505709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 505809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5059a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 5060a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Runs the query with the supplied contact ID and lookup ID. If the query succeeds, 5061a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * it returns the resulting cursor, otherwise it returns null and the calling 5062a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * method needs to resolve the lookup key and rerun the query. 5063a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 5064a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private Cursor queryWithContactIdAndLookupKey(SQLiteQueryBuilder lookupQb, 5065a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteDatabase db, Uri uri, 5066a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection, String selection, String[] selectionArgs, 5067a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String sortOrder, String groupBy, String limit, 5068a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn, long contactId, String lookupKeyColumn, String lookupKey) { 5069a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] args; 5070a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (selectionArgs == null) { 5071a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[2]; 5072a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 5073a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[selectionArgs.length + 2]; 5074a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 5075a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5076a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[0] = String.valueOf(contactId); 5077a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[1] = Uri.encode(lookupKey); 5078a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(contactIdColumn + "=? AND " + lookupKeyColumn + "=?"); 5079a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 5080a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov groupBy, limit); 5081a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c.getCount() != 0) { 5082a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 5083a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5084a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5085a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov c.close(); 5086a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return null; 5087a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 508809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5089bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 5090bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 5091bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 5092bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 5093ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5094bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 5095bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 5096ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 5097ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5098bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 5099bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 5100bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 5101bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5102de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 5103ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5104ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5105ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 5106ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 5107ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 5108ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 5109ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 5110ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder) { 5111ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 5112ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5113ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 5114ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 5115ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 5116ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 5117ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 5118ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 5119ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 5120ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 5121ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 5122ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 5123ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 5124ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5125ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 5126ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 5127ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5128ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5129bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 5130ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 5131bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 5132bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "SUBSTR(" + sortKey + ",1,1) AS " + AddressBookIndexQuery.LETTER); 5133bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5134bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 5135bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 5136bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 5137bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 5138bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 5139bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 5140bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 5141ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 5142bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "GET_PHONEBOOK_INDEX(SUBSTR(" + sortKey + ",1,1),'" + locale + "')" 5143bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 5144ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 5145ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov "COUNT(" + Contacts._ID + ") AS " + AddressBookIndexQuery.COUNT); 5146ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 5147ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5148f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 5149ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 5150ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 5151ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5152ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 5153f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 5154ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 5155ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 5156bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 5157bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 5158bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5159bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 5160bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 5161bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 5162ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 5163f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 5164bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 5165bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 5166bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 5167bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 5168bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 5169bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 5170bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 5171bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 5172bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 5173bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 5174bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5175bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 5176bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 5177bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 5178bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 5179bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5180bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 5181bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 5182bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 5183ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5184ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5185ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov final Bundle bundle = new Bundle(); 5186ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 5187f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 5188ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return new CursorWrapper(cursor) { 5189ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5190ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov @Override 5191ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov public Bundle getExtras() { 5192ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return bundle; 5193ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5194ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 5195ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 5196f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 5197ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5198ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5199ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 52002d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 520192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 520292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 520392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 520492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 52052d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 52062d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 52075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 52085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 52095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 521092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 521192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 521292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 521392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 521492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 521592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 521692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 521792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 521892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 521992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 522092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 522192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 522292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 522392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 522492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 522592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 522692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 522792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 522892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 52295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 52305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 52335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 52365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 52375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 52395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 52405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 52415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 52425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 52435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 52445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 52465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 52475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 52485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 52495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 52525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 52535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 52545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 52555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 52565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 525792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 52585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 52595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 52605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 52635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 52645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 52665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 52675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 52685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 52695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 52705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 52715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 52725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 52735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 52745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 52755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 527692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 527792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 52785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 52795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 52805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 52815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 52855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 52865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 52895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 529192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 529292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 52935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 52955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 52965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 52975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 529892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 52995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 53005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 53015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 53025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 53035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 530492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 53055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 530792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 530892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 530992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 531092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 53115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 53125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 531392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 531492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 531592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 53165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 531892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 531992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 53205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 532192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 532292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 532392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 532492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 532592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountType = c.getString(LookupByRawContactIdQuery.ACCOUNT_TYPE); 532692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 532792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 532892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 532992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 533092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 533192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 533292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 533392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 533492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 533592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 533692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 533792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 533892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 533992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 534092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 534192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 53425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 534492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 534592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 534692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 534792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 534892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 534992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 535092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 535192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 535292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 535392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 535492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 535592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 535692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 535792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 535892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_TYPE = 1; 535992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 536092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 536192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 536292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 536392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 536492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 53655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 53665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 53675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 53685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 536992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 537092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 53715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 53725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 53735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 53765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 53775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 53785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 53795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 53805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 53815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 53825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 53835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 53845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 53855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 53865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 53875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 53885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 53895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 539092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 539192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 539292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 53935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 53945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 53955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 53965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 54005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 54015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 54025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 54035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 54045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 54055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 540692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 540792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 540892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 540992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 541092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 541192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 541292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 541392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 541492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 541592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 541692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 5417ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 5418ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(db, rawContactId); 5419ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 5420ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 54215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 54225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 54235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 54245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 54255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 54265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 54275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 54285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 54295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 54305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 54315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 54325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 54335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 54345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 54355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 54365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 54375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 54385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 54395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 54405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 54415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 54425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 54435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 54445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 54455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 54465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 54475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 54485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 54495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 54505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 54515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 54525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 54535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 54545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 54555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 5456763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 5457763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 545882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5459916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 5460916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 5461916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 5462916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5463916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5464916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 5465916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 5466916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 5467916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 5468916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 5469916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String[] projection, String filter) { 5470916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5471916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5472916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 5473916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5474916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(" JOIN (SELECT " + 5475916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov RawContacts.CONTACT_ID + " AS snippet_contact_id"); 5476916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5477916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA_ID)) { 5478916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", " + DataColumns.CONCRETE_ID + " AS " 5479916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov + SearchSnippetColumns.SNIPPET_DATA_ID); 5480916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5481916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 54829c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA1)) { 54839c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA1 + " AS " + SearchSnippetColumns.SNIPPET_DATA1); 5484916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5485916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 54869c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA2)) { 54879c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA2 + " AS " + SearchSnippetColumns.SNIPPET_DATA2); 5488916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5489916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 54909c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA3)) { 54919c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA3 + " AS " + SearchSnippetColumns.SNIPPET_DATA3); 54929c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 54939c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov 54949c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA4)) { 54959c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA4 + " AS " + SearchSnippetColumns.SNIPPET_DATA4); 5496916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5497916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5498916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_MIMETYPE)) { 5499916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", (" + 5500916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov "SELECT " + MimetypesColumns.MIMETYPE + 5501916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " FROM " + Tables.MIMETYPES + 5502916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + MimetypesColumns._ID + "=" + DataColumns.MIMETYPE_ID + 5503916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov ") AS " + SearchSnippetColumns.SNIPPET_MIMETYPE); 5504916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5505916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5506c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS + " WHERE "); 5507c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov 5508c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov if (!TextUtils.isEmpty(filter)) { 5509c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append(DataColumns.CONCRETE_ID + " IN ("); 5510c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov 5511c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov // Construct a query that gives us exactly one data _id per matching contact. 5512c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov // MIN stands in for ANY in this context. 5513c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append( 5514c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov "SELECT MIN(" + Tables.NAME_LOOKUP + "." + NameLookupColumns.DATA_ID + ")" + 5515c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5516c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5517c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " ON (" + RawContactsColumns.CONCRETE_ID 5518c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov + "=" + Tables.NAME_LOOKUP + "." + NameLookupColumns.RAW_CONTACT_ID + ")" + 5519c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + " GLOB '"); 5520c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append(NameNormalizer.normalize(filter)); 5521c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 5522c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + ")" + 5523c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " GROUP BY " + RawContactsColumns.CONCRETE_CONTACT_ID + 5524c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov ")"); 5525c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov } else { 5526c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append("0"); // Empty filter - return an empty set 5527c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov } 5528c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov 5529c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append(") ON (" + Contacts._ID + "=snippet_contact_id)"); 5530916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5531916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 5532916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 5533916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5534916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5535916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void appendContactsTables(StringBuilder sb, Uri uri, String[] projection) { 5536763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 5537f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5538763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5539763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5540d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5541763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5542763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 5543a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 5544a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 554582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 5546ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 5547763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 5548763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 5549763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 5550f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5551763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5552763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5553d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5554763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5555763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 5556763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 5557763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 5558763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 5559763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5560763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 5561a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForRawEntities(SQLiteQueryBuilder qb, Uri uri) { 5562a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(mDbHelper.getRawEntitiesView(shouldExcludeRestrictedData(uri))); 5563a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sRawEntityProjectionMap); 556446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 556546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 556646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 556782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 556882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 556982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5570a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(mDbHelper.getDataView(shouldExcludeRestrictedData(uri))); 557182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 557282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 5573a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, RawContacts.CONTACT_ID); 5574a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 5575a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 5576a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 55773296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 557882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 557982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 558082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 5581ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 5582ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 55830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 55840a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 55850a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5586b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 55870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 5588a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 5589a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 55900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 5591a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 5592a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 5593a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5594a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5595a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForEntities(SQLiteQueryBuilder qb, Uri uri, 5596a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection) { 5597a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5598a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(mDbHelper.getEntitiesView(shouldExcludeRestrictedData(uri))); 5599a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" data"); 5600a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5601a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts.Entity.CONTACT_ID); 5602a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 5603a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, Contacts.Entity.DATA_ID); 5604a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, Contacts.Entity.DATA_ID); 5605a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5606a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 5607a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sEntityProjectionMap); 5608a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendAccountFromParameter(qb, uri); 5609a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5610a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5611a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactStatusUpdateJoin(StringBuilder sb, String[] projection, 5612a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lastStatusUpdateIdColumn) { 5613a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 5614a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS, 5615a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 5616a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 5617a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 5618a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 5619a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 5620a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 5621a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + lastStatusUpdateIdColumn + "=" 5622a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 56230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 5624a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 56250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 5626a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataStatusUpdateJoin(StringBuilder sb, String[] projection, 5627a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 5628b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 56290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 56300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 56310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 56320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 56330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 56340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 5635a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 5636a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + dataIdColumn + ")"); 56370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 5638a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5639a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5640a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactPresenceJoin(StringBuilder sb, String[] projection, 5641a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn) { 5642a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 5643a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_PRESENCE, Contacts.CONTACT_CHAT_CAPABILITY)) { 5644a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 5645a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + contactIdColumn + " = " 5646a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + ")"); 5647a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5648a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5649a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5650a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataPresenceJoin(StringBuilder sb, String[] projection, 5651a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 5652a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.PRESENCE, Data.CHAT_CAPABILITY)) { 5653a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 5654a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdates.DATA_ID + "=" + dataIdColumn + ")"); 5655a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5656a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5657a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5658a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private boolean shouldExcludeRestrictedData(Uri uri) { 5659a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov // Note: currently, "export only" equals to "restricted", but may not in the future. 5660a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov boolean excludeRestrictedData = readBooleanQueryParameter(uri, 5661a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.FOR_EXPORT_ONLY, false); 5662a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (excludeRestrictedData) { 5663a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return true; 5664a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5665a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5666a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5667a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5668a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (requestingPackage != null) { 5669a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5670a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5671a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5672a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return false; 56730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 56740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 56754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 5676f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 5677f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 5678e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5679e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 5680e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 5681e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 5682fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 5683fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 5684e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 5685e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5686e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 5687e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 5688e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 5689e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 56904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 56914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 56924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 56934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 56944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 56954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 56964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 56974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 56984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5699e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 5700f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 5701f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 5702e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5703e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 5704e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 5705e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 5706fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 5707fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 5708e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 5709e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5710e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 5711e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 5712e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 5713e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 5714e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 5715e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 5716e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 5717e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 5718e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 5719e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 5720e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 5721e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 5722e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5723e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 5724e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 5725e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 5726e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5727e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5728e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 57297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 5730c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 5731c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 5732c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 5733c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 5734c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 5735f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 5736f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String limitParam = getQueryParameter(uri, "limit"); 5737c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 5738c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5739c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5740c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 5741c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 5742c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 5743c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 5744c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 5745c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5746c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5747c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 5748c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 5749c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 5750c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5751c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5752c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5753c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 575400ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 5755d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 575670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 575770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 5758fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0"; 575970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 576070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 576170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 576270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 5763d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 576470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 576567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 57665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 57675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 5768619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5769619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5770619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 5771b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 5772ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 5773b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 5774b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 5775a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 5776ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return openPhotoFile(uri, mode, 5777e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=" + Contacts.PHOTO_ID + " AND " + RawContacts.CONTACT_ID + "=?", 5778e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 5779e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5780b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5781e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 5782ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return openPhotoFile(uri, mode, 5783e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=? AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'", 57844da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 5785d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5786d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5787f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 578842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 578942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann mSelectionArgs1[0] = String.valueOf(lookupContactIdByLookupKey(mDb, lookupKey)); 579042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + "=?"; 579142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 579242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 579342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 579442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 579542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 579642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann outputRawContactsAsVCard(localStream, selection, mSelectionArgs1); 5797ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return buildFileDescriptor(localStream); 579842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 579942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 580042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 580142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 580242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 580342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 580442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 5805d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 5806d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 580742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 580842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 5809d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 581042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 5811d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 581242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 5813d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(lookupContactIdByLookupKey(mDb, lookupKey)); 581442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 581542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 581642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 581742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 5818d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5819d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 5820d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 5821d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 5822d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 5823d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann outputRawContactsAsVCard(localStream, selection, null); 5824ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return buildFileDescriptor(localStream); 5825d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5826b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5827b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 5828fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("File does not exist", 5829fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov uri)); 5830b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5831b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5832b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5833ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert private ParcelFileDescriptor openPhotoFile(Uri uri, String mode, String selection, 5834e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String[] selectionArgs) 5835e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 5836e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 5837e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("Mode " + mode 5838e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 5839e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5840e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 5841e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 5842e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 5843e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 5844e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 5845ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return DatabaseUtils.blobFileDescriptorForQuery(db, sql, selectionArgs); 5846e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5847e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 5848d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 5849d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5850d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5851ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert * Returns a {@link ParcelFileDescriptor} backed by the 5852d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 5853d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5854ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert private ParcelFileDescriptor buildFileDescriptor(ByteArrayOutputStream stream) { 5855d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 5856d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 5857d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5858d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 5859d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5860ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return ParcelFileDescriptor.fromData(byteData, CONTACT_MEMORY_FILE_NAME); 5861d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 5862ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert Log.w(TAG, "Problem writing stream into an ParcelFileDescriptor: " + e.toString()); 5863ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return null; 5864d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5865d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5866d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5867d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5868d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 5869d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 5870d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 5871d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5872d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 5873d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 5874d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 58757a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 58767a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa new VCardComposer(context, VCardConfig.VCARD_TYPE_DEFAULT, false); 5877d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 5878d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5879f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 58807a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa if (!composer.init(selection, selectionArgs)) { 58817a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 5882d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 58837a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa } 5884d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5885d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 5886d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 5887d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 5888d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5889d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5890d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 5891d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5892b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 58934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 58944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 5895a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 58964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 5897b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 5898be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 58992d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 5900b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 5901b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 5902b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 5903f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 590442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 5905f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 5906f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov case CONTACTS_ID_PHOTO: 5907f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov return "image/png"; 5908b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 5909be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 5910b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 5911b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 5912508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 5913b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 591448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 591548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 591648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 591748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 59189005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 59199005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 592048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 592148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 592248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 592348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 592448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 592548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 592648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 592748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 5928b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 5929b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 5930b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 5931b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 5932b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 5933b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 5934b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 5935b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 5936c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 5937c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 5938c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 5939c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 5940d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES: 5941d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_TYPE; 5942d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID: 5943d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_ITEM_TYPE; 594461efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 594561efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 59464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 59474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 59487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 594909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public String[] getDefaultProjection(Uri uri) { 595009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov final int match = sUriMatcher.match(uri); 595109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov switch (match) { 595209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS: 595309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP: 595409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_ID: 595509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP_ID: 595609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 595709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsProjectionMap.getColumnNames(); 595809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 59598727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov case CONTACTS_ID_ENTITIES: 59608727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov return sEntityProjectionMap.getColumnNames(); 59618727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov 596209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_VCARD: 596309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_MULTI_VCARD: 596409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsVCardProjectionMap.getColumnNames(); 596509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 596609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS: 596709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS_ID: 596809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sRawContactsProjectionMap.getColumnNames(); 596909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 597009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DATA_ID: 597109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES: 597209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES_ID: 597309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS: 597409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS_ID: 597509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS: 597609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS_ID: 597709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDataProjectionMap.getColumnNames(); 597809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 597909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONE_LOOKUP: 598009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sPhoneLookupProjectionMap.getColumnNames(); 598109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 598209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 598309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 598409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sAggregationExceptionsProjectionMap.getColumnNames(); 598509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 598609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case SETTINGS: 598709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sSettingsProjectionMap.getColumnNames(); 598809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 598909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES: 599009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES_ID: 599109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDirectoryProjectionMap.getColumnNames(); 599209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 599309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov default: 599409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return null; 599509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 599609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 599709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 59985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void setDisplayName(long rawContactId, int displayNameSource, 59995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary, String displayNameAlternative, String phoneticName, 60005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int phoneticNameStyle, String sortKeyPrimary, String sortKeyAlternative) { 60015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(1, displayNameSource); 60025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 2, displayNamePrimary); 60035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 3, displayNameAlternative); 60045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 4, phoneticName); 60055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(5, phoneticNameStyle); 60065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 6, sortKeyPrimary); 60075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 7, sortKeyAlternative); 60085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(8, rawContactId); 600925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 60103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 60113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 601273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 601373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 601473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 601573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 6016a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.add(rawContactId); 601773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 601873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 6019c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 6020c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 6021c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 6022c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 6023c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 6024c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 6025653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 6026c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 6027653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 6028653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 6029c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 6030c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 6031c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 6032c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 6033c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 6034c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 6035c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 6036c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 6037c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 6038653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 6039c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 6040653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 6041653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 6042c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 6043c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 6044ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 6045813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public String insertNameLookupForEmail(long rawContactId, long dataId, String email) { 6046f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 6047813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 6048f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6049f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6050b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String address = mDbHelper.extractHandleFromEmailAddress(email); 6051b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (address == null) { 6052813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 6053f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6054f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6055f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 6056f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 6057813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return address; 6058f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6059f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6060f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 6061f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 6062f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 6063f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 6064f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 6065f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 6066f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6067f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6068f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 6069f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 6070f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6071f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6072a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 6073a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 6074a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 6075a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 6076a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 6077a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 6078a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 6079a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 6080a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 6081a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 6082a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 6083f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6084d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name, 6085d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov int fullNameStyle) { 6086d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle); 6087f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6088f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6089f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 6090f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6091f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 6092f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 6093f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6094f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6095f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 6096f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 6097f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 6098f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 6099f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6100f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6101f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 6102f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 6103d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 6104f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6105f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6106f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 610748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov public void insertNameLookupForPhoneticName(long rawContactId, long dataId, 610848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov ContentValues values) { 610948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (values.containsKey(StructuredName.PHONETIC_FAMILY_NAME) 611048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov || values.containsKey(StructuredName.PHONETIC_GIVEN_NAME) 611148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov || values.containsKey(StructuredName.PHONETIC_MIDDLE_NAME)) { 611248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, 611348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_FAMILY_NAME), 611448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_MIDDLE_NAME), 611548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_GIVEN_NAME)); 611648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 611748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 611848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 611948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov public void insertNameLookupForPhoneticName(long rawContactId, long dataId, String familyName, 612048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov String middleName, String givenName) { 612148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.setLength(0); 612248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (familyName != null) { 612348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(familyName.trim()); 612448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 612548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (middleName != null) { 612648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(middleName.trim()); 612748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 612848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (givenName != null) { 612948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(givenName.trim()); 613048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 613148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 613248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (mSb.length() > 0) { 613348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookup(rawContactId, dataId, NameLookupType.NAME_COLLATION_KEY, 613448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov NameNormalizer.normalize(mSb.toString())); 613548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 61363b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov 61373b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov if (givenName != null) { 61383b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov // We want the phonetic given name to be used for search, but not for aggregation, 61393b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov // which is why we are using NAME_SHORTHAND rather than NAME_COLLATION_KEY 61403b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov insertNameLookup(rawContactId, dataId, NameLookupType.NAME_SHORTHAND, 61413b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov NameNormalizer.normalize(givenName.trim())); 61423b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov } 614348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 614448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 6145f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 6146f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 6147f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 6148f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 61495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(1, rawContactId); 61505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(2, dataId); 61515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(3, lookupType); 61525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mNameLookupInsert, 4, name); 6153f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 6154f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6155f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6156f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 6157f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 6158f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 6159f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 61605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupDelete.bindLong(1, dataId); 6161f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 6162f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6163f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 61642d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 6165d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 6166d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 6167d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 6168d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 6169d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 6170d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 6171d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 6172e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 6173916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 6174916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 6175e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 6176e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 61775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 6178c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 61797318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam); 6180c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 6181c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6182c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 61837318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam) { 61847318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), true); 61855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 61865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 61875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 61887318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov boolean allowEmailMatch) { 6189d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 6190dc947a9d03279eab0fb7c3b9d8ffbb492c1e2062Dmitri Plotnikov "SELECT " + NameLookupColumns.RAW_CONTACT_ID + 6191d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 6192d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 6193d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 61945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 6195a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 6196a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 6197a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 61984cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao + NameLookupType.NAME_SHORTHAND + "," 6199f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee + NameLookupType.ORGANIZATION + "," 620089f1f71495aedc58252b3f58a46a036986c319d2Dmitri Plotnikov + NameLookupType.NAME_CONSONANTS); 620120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 620220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 620320938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 620489f1f71495aedc58252b3f58a46a036986c319d2Dmitri Plotnikov sb.append("))"); 6205ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 6206ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 62074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 62087a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * Takes components of a name from the query parameters and returns a cursor with those 62097a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * components as well as all missing components. There is no database activity involved 62107a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * in this so the call can be made on the UI thread. 62117a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov */ 62127a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private Cursor completeName(Uri uri, String[] projection) { 62137a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (projection == null) { 62147a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov projection = sDataProjectionMap.getColumnNames(); 62157a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62167a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 62177a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ContentValues values = new ContentValues(); 62187a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredNameRowHandler handler = 62197a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov (StructuredNameRowHandler) getDataRowHandler(StructuredName.CONTENT_ITEM_TYPE); 62207a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 62217a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov copyQueryParamsToContentValues(values, uri, 62227a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.DISPLAY_NAME, 62237a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PREFIX, 62247a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.GIVEN_NAME, 62257a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.MIDDLE_NAME, 62267a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.FAMILY_NAME, 62277a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.SUFFIX, 62287a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_NAME, 62297a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_FAMILY_NAME, 62307a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_MIDDLE_NAME, 62317a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_GIVEN_NAME 62327a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ); 62337a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 62347a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov handler.fixStructuredNameComponents(values, values); 62357a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 62367a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 62377a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov Object[] row = new Object[projection.length]; 62387a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (int i = 0; i < projection.length; i++) { 62397a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov row[i] = values.get(projection[i]); 62407a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62417a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.addRow(row); 62427a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return cursor; 62437a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62447a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 62457a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private void copyQueryParamsToContentValues(ContentValues values, Uri uri, String... columns) { 62467a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (String column : columns) { 62477a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String param = uri.getQueryParameter(column); 62487a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (param != null) { 62497a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov values.put(column, param); 62507a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62517a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62527a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62537a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 62547a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 62557a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov /** 62564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 62574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 62584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 6259b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 6260b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 6261b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 6262b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 6263b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 62644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 62654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 6266b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 6267b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 6268b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 6269caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 62705e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 62715e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 62725e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 62735e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 62745e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 62755e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 62765e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 62775e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 62785e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 62795e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 62805e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 6281caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 6282caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 6283caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 6284df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 6285df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 6286caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 6287caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 6288caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 6289caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 62906f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 6291caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 62926f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 6293caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 6294f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 629573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 629673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov * Returns true if the specified account type is writable. 629773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 629873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov protected boolean isWritableAccount(String accountType) { 6299bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov if (accountType == null) { 6300bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 6301bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 6302bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 630373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov Boolean writable = mAccountWritability.get(accountType); 630473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 630573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 630673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 630773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 6308627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 6309627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 6310627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 6311627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 631273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov accountType.equals(sync.accountType)) { 631373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 631473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 6315627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 6316627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 6317627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 6318627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 6319627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 632073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 632173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 632273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 632373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 632473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 632573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.put(accountType, writable); 632673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 6327627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 6328b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 6329d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 6330f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 6331f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 6332f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6333f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 6334f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 6335f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 6336f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 6337f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6338f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6339f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 6340f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 6341f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 6342f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6343f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6344f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 6345f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6346f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 6347f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 6348f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6349f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6350f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 6351f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 6352f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 6353f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 6354f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 6355f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6356f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6357f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 6358f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 6359f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 6360f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 6361f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 6362f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 6363f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 6364f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6365f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6366f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 6367f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 6368f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6369f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 6370f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 6371f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 6372f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 6373f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 6374f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 6375f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6376f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6377f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 6378f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6379f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 6380f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 6381f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6382f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6383f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 6384f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 6385f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 6386f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6387f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6388f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6389f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 6390f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 6391f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 6392f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 6393f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 6394f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6395f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6396f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 6397f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 63985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 63995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindString(SQLiteStatement stmt, int index, String value) { 64005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 64015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 64025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 64035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindString(index, value); 64045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 64055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 64065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 64075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindLong(SQLiteStatement stmt, int index, Number value) { 64085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 64095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 64105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 64115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindLong(index, value.longValue()); 64125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 64135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 64144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 6415