ContactsProvider2.java revision fd2a6a5b7ecbbec6298182daee3b252896f82ea4
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 1953214b3ed12b0ff9cb589b6559311f2ac142f2e3Bjorn Bringertimport com.android.common.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; 64f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringertimport android.content.res.AssetFileDescriptor; 654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 66ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.CursorWrapper; 67ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 6809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor; 6909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor.RowBuilder; 704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 7108ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwoodimport android.database.sqlite.SQLiteDoneException; 724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 74d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.net.Uri.Builder; 75bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Binder; 766ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 77bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Handler; 78bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.HandlerThread; 79bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Message; 80ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringertimport android.os.ParcelFileDescriptor; 81bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Process; 82b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 8315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikovimport android.os.StrictMode; 840dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikovimport android.os.SystemClock; 850e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 863d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 87508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 883de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 89b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 9097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 9197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 9297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 9397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 9497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 9597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 9697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 9797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 9897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 99ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 1003de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 1015b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions; 1023de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 103d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory; 1043de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 105bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.provider.ContactsContract.Intents; 1063de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 10709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 1083de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 109916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 1103de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 11182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 11297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.LiveFolders; 11397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.OpenableColumns; 11497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.SyncStateContract; 115a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 116a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 117c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 119d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 120b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 121d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 122d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 12342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.text.SimpleDateFormat; 1247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 12642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.util.Date; 127b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1280e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 130622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 131b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1320e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 133ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1384f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1395b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 140caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 141bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 142bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 143bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 14515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_INITIALIZE = 0; 14615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_OPEN_WRITE_ACCESS = 1; 14715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS = 2; 14815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_ACCOUNTS = 3; 14915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_LOCALE = 4; 15015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM = 5; 15115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_PROVIDER_STATUS = 6; 15215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_DIRECTORIES = 7; 153fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private static final int BACKGROUND_TASK_CHANGE_LOCALE = 8; 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 1670dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final String PROPERTY_AGGREGATION_ALGORITHM = "aggregation_v2"; 1680dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final int PROPERTY_AGGREGATION_ALGORITHM_VERSION = 2; 1690dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 1700e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1710e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 172a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 174dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov private static final String TIMES_CONTACTED_SORT_COLUMN = "times_contacted_sort"; 1755e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 176d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 177dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov + TIMES_CONTACTED_SORT_COLUMN + " DESC, " 1789b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 179d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 180d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 181d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 182d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1836e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 1849b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 1859b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1869b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 1879b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 1886e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 1899b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 1909b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1919b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 1929b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 193de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 194de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 195d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 196d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 199a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_DATA = 1004; 2005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 2015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 2025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 2035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 204a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_PHOTO = 1009; 205f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 20642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann private static final int CONTACTS_AS_MULTI_VCARD = 1011; 2072149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov private static final int CONTACTS_LOOKUP_DATA = 1012; 2082149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ID_DATA = 1013; 209a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_ENTITIES = 1014; 210a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ENTITIES = 1015; 211a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ID_ENTITIES = 1016; 2124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 2145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 2155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 21646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 2174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2186bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2196bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 220ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 22148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 22248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 22348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 22448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 22548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 22648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 22748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 22848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 229a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2306bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 2316bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 232b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 233b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 234b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 23582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 23682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 2371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 23831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 23931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 240eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 241eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 242ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 243ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 244ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 245ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 24635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 247b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 24835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 249c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 250c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 251c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2541b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2551b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 25746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 25846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 25909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 26009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 261d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES = 17001; 262d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES_ID = 17002; 263d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 2647a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private static final int COMPLETE_NAME = 18000; 2657a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 266dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID = 267dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 268dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME 269dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 270dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE 271dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_TYPE 272dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + " != 0"; 273dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 274dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID = 275dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 276dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 277dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 278dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 279dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND " 280dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + Groups.AUTO_ADD + " != 0"; 281dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 282dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String[] PROJECTION_GROUP_ID 283dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana = new String[]{Tables.GROUPS + "." + Groups._ID}; 284dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 285dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_GROUPMEMBERSHIP_DATA = DataColumns.MIMETYPE_ID + "=? " 286dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.GROUP_ROW_ID + "=? " 287dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.RAW_CONTACT_ID + "=?"; 288dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 289dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_STARRED_FROM_RAW_CONTACTS = 290dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT " + RawContacts.STARRED 291dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?"; 292dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 293d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 294f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 295f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 296f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 29767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 29867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2996cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 3003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 301f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 302ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 303ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 304d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 30567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 306d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 307ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 309f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov interface RawContactsQuery { 31019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 31119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 31219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 313ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 314ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 315ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 31619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 31719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 31819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 319ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 320ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 32119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 32219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 323c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 324df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 325caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 32671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 32771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 32871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 32971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 33071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 33171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 33271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 33371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 33471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 33571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 33671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 33771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 33871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 33971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 340a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 341a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 342a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 343a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 344a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 345a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 346a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 347a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 348a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 349a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 350a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 351a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 352c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Current contacts - those contacted within the last 3 days (in seconds) 353c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_CURRENT = 3 * 24 * 60 * 60; 354c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 355c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Recent contacts - those contacted within the last 30 days (in seconds) 356c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_RECENT = 30 * 24 * 60 * 60; 357c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 358c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final String TIME_SINCE_LAST_CONTACTED = 359c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov "(strftime('%s', 'now') - " + Contacts.LAST_TIME_CONTACTED + "/1000)"; 360c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 361c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov /* 362c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * Sorting order for email address suggestions: first starred, then the rest. 363c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * Within the starred/unstarred groups - three buckets: very recently contacted, then fairly 364c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * recently contacted, then the rest. Within each of the bucket - descending count 365c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * of times contacted. If all else fails, alphabetical. (Super)primary email 366c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * address is returned before other addresses for the same contact. 367c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov */ 368c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final String EMAIL_FILTER_SORT_ORDER = 369c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov "(CASE WHEN " + Contacts.STARRED + "=1 THEN 0 ELSE 1 END), " 370c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + "(CASE WHEN " + TIME_SINCE_LAST_CONTACTED + " < " + EMAIL_FILTER_CURRENT + " THEN 0 " 371c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + " WHEN " + TIME_SINCE_LAST_CONTACTED + " < " + EMAIL_FILTER_RECENT + " THEN 1 " 372c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + " ELSE 2 END)," 373c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + Contacts.TIMES_CONTACTED + " DESC, " 374c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + Contacts.DISPLAY_NAME + ", " 375c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + Data.CONTACT_ID + ", " 376c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + Data.IS_SUPER_PRIMARY + " DESC"; 377c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 378916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 379916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 380916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 381916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 382916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NICKNAME + "," + 383916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_SHORTHAND + "," + 384f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.ORGANIZATION + "," + 385f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.NAME_CONSONANTS; 386916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 387f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov /** 388f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * If any of these columns are used in a Data projection, there is no point in 389f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * using the DISTINCT keyword, which can negatively affect performance. 390f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov */ 391f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov private static final String[] DISTINCT_DATA_PROHIBITING_COLUMNS = { 392f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data._ID, 393f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.RAW_CONTACT_ID, 394f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.NAME_RAW_CONTACT_ID, 395f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 396f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 397f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.DIRTY, 398f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.NAME_VERIFIED, 399f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SOURCE_ID, 400f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.VERSION, 401f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov }; 402916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 403f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsColumns = ProjectionMap.builder() 404f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CUSTOM_RINGTONE) 405f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME) 406f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_ALTERNATIVE) 407f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_SOURCE) 408f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.IN_VISIBLE_GROUP) 409f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LAST_TIME_CONTACTED) 410f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LOOKUP_KEY) 411f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME) 412f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME_STYLE) 413f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHOTO_ID) 4143d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_URI) 4153d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_THUMBNAIL_URI) 416f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SEND_TO_VOICEMAIL) 417f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_ALTERNATIVE) 418f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_PRIMARY) 419f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.STARRED) 420f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.TIMES_CONTACTED) 421cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 422f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 423f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 424f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsPresenceColumns = ProjectionMap.builder() 425f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 426f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE) 427f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 428f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 429f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 430f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 431f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 432f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 433f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 434f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 435f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 436f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 437f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 438f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 439f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 440f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 441f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSnippetColumns = ProjectionMap.builder() 442f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_MIMETYPE) 443f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_DATA_ID) 444f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_DATA1) 445f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_DATA2) 446f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_DATA3) 447f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(SearchSnippetColumns.SNIPPET_DATA4) 448f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 449f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 450f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 451f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactColumns = ProjectionMap.builder() 452f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_NAME) 453f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_TYPE) 454f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DIRTY) 455f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.NAME_VERIFIED) 456f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SOURCE_ID) 457f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.VERSION) 458f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 459f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 460f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactSyncColumns = ProjectionMap.builder() 461f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC1) 462f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC2) 463f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC3) 464f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC4) 465f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 466f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 467f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataColumns = ProjectionMap.builder() 468f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA1) 469f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA2) 470f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA3) 471f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA4) 472f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA5) 473f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA6) 474f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA7) 475f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA8) 476f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA9) 477f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA10) 478f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA11) 479f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA12) 480f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA13) 481f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA14) 482f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA15) 483f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA_VERSION) 484f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_PRIMARY) 485f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_SUPER_PRIMARY) 486f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.MIMETYPE) 487f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RES_PACKAGE) 488f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC1) 489f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC2) 490f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC3) 491f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC4) 492f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(GroupMembership.GROUP_SOURCE_ID) 493f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 494f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 495f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactPresenceColumns = ProjectionMap.builder() 496f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 497f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.PRESENCE) 498f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 499f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.CHAT_CAPABILITY) 500f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 501f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 502f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 503f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 504f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 505f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 506f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 507f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 508f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 509f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 510f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 511f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 512f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataPresenceColumns = ProjectionMap.builder() 513f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.PRESENCE, Tables.PRESENCE + "." + StatusUpdates.PRESENCE) 514f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CHAT_CAPABILITY, Tables.PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 515f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS, StatusUpdatesColumns.CONCRETE_STATUS) 516f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_TIMESTAMP, StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 517f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_RES_PACKAGE, StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 518f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_LABEL, StatusUpdatesColumns.CONCRETE_STATUS_LABEL) 519f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_ICON, StatusUpdatesColumns.CONCRETE_STATUS_ICON) 520f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 521f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 522038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 523f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sCountProjectionMap = ProjectionMap.builder() 524f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(BaseColumns._COUNT, "COUNT(*)") 525f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 526f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 527e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 528f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionMap = ProjectionMap.builder() 529f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts._ID) 530f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 531f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.NAME_RAW_CONTACT_ID) 532f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 533f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsPresenceColumns) 534f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 535f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 536916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 537f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionWithSnippetMap = ProjectionMap.builder() 538f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 539f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sSnippetColumns) 540f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 541916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5425e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 543f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentStarredProjectionMap = ProjectionMap.builder() 544f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 545f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(TIMES_CONTACTED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 546f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 547f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 548f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder() 549f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 550f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(TIMES_CONTACTED_SORT_COLUMN, Contacts.TIMES_CONTACTED) 551f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 552f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 553f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 554f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsVCardProjectionMap = ProjectionMap.builder() 555f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME + " || '.vcf'") 556f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.SIZE, "NULL") 557f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 558f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 559ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 560f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactsProjectionMap = ProjectionMap.builder() 561f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 562f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 563f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 564f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_PRIMARY) 565f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_ALTERNATIVE) 566f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_SOURCE) 567f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME) 568f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME_STYLE) 569f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_PRIMARY) 570f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_ALTERNATIVE) 571f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.TIMES_CONTACTED) 572f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.LAST_TIME_CONTACTED) 573f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CUSTOM_RINGTONE) 574f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SEND_TO_VOICEMAIL) 575f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 576f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.AGGREGATION_MODE) 577f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 578f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 579f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 580f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 581a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the raw entity view*/ 582f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawEntityProjectionMap = ProjectionMap.builder() 583f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 584f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 585f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.Entity.DATA_ID) 586f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.IS_RESTRICTED) 587f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 588f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 589f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 590f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 591f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 592f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 593f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 594a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the contact entity view*/ 595f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sEntityProjectionMap = ProjectionMap.builder() 596f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity._ID) 597f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.CONTACT_ID) 598f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.RAW_CONTACT_ID) 599f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DATA_ID) 600f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.NAME_RAW_CONTACT_ID) 601f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DELETED) 602f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.IS_RESTRICTED) 603f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 604f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 605f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 606f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 607f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 608f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 609f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 610f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 612f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataProjectionMap = ProjectionMap.builder() 613f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID) 614f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RAW_CONTACT_ID) 615f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CONTACT_ID) 616f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.NAME_RAW_CONTACT_ID) 617f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 618f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 619f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 620f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 621f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 622f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 623f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 625f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDistinctDataProjectionMap = ProjectionMap.builder() 626f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID, "MIN(" + Data._ID + ")") 627f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 628f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 629f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 630f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 631f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 632f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 633f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6349261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 635f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sPhoneLookupProjectionMap = ProjectionMap.builder() 636f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup._ID, "contacts_view." + Contacts._ID) 637f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LOOKUP_KEY, "contacts_view." + Contacts.LOOKUP_KEY) 638f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.DISPLAY_NAME, "contacts_view." + Contacts.DISPLAY_NAME) 639f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LAST_TIME_CONTACTED, "contacts_view." + Contacts.LAST_TIME_CONTACTED) 640f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TIMES_CONTACTED, "contacts_view." + Contacts.TIMES_CONTACTED) 641f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.STARRED, "contacts_view." + Contacts.STARRED) 642f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.IN_VISIBLE_GROUP, "contacts_view." + Contacts.IN_VISIBLE_GROUP) 643f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.PHOTO_ID, "contacts_view." + Contacts.PHOTO_ID) 6443d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_URI, "contacts_view." + Contacts.PHOTO_URI) 6453d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_THUMBNAIL_URI, "contacts_view." + Contacts.PHOTO_THUMBNAIL_URI) 646f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.CUSTOM_RINGTONE, "contacts_view." + Contacts.CUSTOM_RINGTONE) 647f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.HAS_PHONE_NUMBER, "contacts_view." + Contacts.HAS_PHONE_NUMBER) 648f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.SEND_TO_VOICEMAIL, "contacts_view." + Contacts.SEND_TO_VOICEMAIL) 649f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.NUMBER, Phone.NUMBER) 650f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TYPE, Phone.TYPE) 651f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LABEL, Phone.LABEL) 6522530512f639c4979fd7371c7dd25dd67e8118124Bai Tao .add(PhoneLookup.NORMALIZED_NUMBER, Phone.NORMALIZED_NUMBER) 653f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 654f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 655ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 656f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsProjectionMap = ProjectionMap.builder() 657f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups._ID) 658f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_NAME) 659f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_TYPE) 660f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SOURCE_ID) 661f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DIRTY) 662f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.VERSION) 663f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.RES_PACKAGE) 664f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE) 665f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE_RES) 666f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.GROUP_VISIBLE) 667f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYSTEM_ID) 668f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DELETED) 669f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.NOTES) 670f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SHOULD_SYNC) 671f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.FAVORITES) 672f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.AUTO_ADD) 673c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov .add(Groups.GROUP_IS_READ_ONLY) 674f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC1) 675f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC2) 676f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC3) 677f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC4) 678f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 679f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 680ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 681f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsSummaryProjectionMap = ProjectionMap.builder() 682f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sGroupsProjectionMap) 683f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_COUNT, 684f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 685f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS 686f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP 687f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Clauses.BELONGS_TO_GROUP 688f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ")") 689f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_WITH_PHONES, 690f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 691f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS 692f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP 693f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Clauses.BELONGS_TO_GROUP 694f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ")") 695f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 696f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 697373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 698f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sAggregationExceptionsProjectionMap = ProjectionMap.builder() 699f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id") 700f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.TYPE) 701f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID1) 702f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID2) 703f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 704f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 705eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 706f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSettingsProjectionMap = ProjectionMap.builder() 707f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_NAME) 708f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_TYPE) 709f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_VISIBLE) 710f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.SHOULD_SYNC) 711f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ANY_UNSYNCED, 712f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 713f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ",(SELECT " 714f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "(CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL" 715f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 716f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE MIN(" + Groups.SHOULD_SYNC + ")" 717f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)" 718f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.GROUPS 719f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 720f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_NAME 721f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 722f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0" 723f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 724f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE 0" 725f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)") 726f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_COUNT, 727f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 728f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 729f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 730f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 731f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 732f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 733f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_WITH_PHONES, 734f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 735f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 736f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 737f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Contacts.HAS_PHONE_NUMBER 738f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 739f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 740f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 741f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 742f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 74382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 744f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStatusUpdatesProjectionMap = ProjectionMap.builder() 745f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PresenceColumns.RAW_CONTACT_ID) 746f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.DATA_ID, DataColumns.CONCRETE_ID) 747f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_ACCOUNT) 748f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_HANDLE) 749f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PROTOCOL) 750f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 751f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // properly enforce uniqueness of null values 752f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CUSTOM_PROTOCOL, 753f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL + "=''" 754f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN NULL" 755f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END)") 756f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PRESENCE) 757f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CHAT_CAPABILITY) 758f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS) 759f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_TIMESTAMP) 760f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_RES_PACKAGE) 761f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_ICON) 762f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_LABEL) 763f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 764f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7651b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 766f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sLiveFoldersProjectionMap = ProjectionMap.builder() 767f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders._ID, Contacts._ID) 768f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders.NAME, Contacts.DISPLAY_NAME) 769f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 770f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // for contacts without a photo 771f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // .add(LiveFolders.ICON_BITMAP, Photos.DATA) 772f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 773f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 774d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** Contains {@link Directory} columns */ 775f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDirectoryProjectionMap = ProjectionMap.builder() 776f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory._ID) 777f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.PACKAGE_NAME) 778f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.TYPE_RESOURCE_ID) 779f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DISPLAY_NAME) 780f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DIRECTORY_AUTHORITY) 781f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_TYPE) 782f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_NAME) 783f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.EXPORT_SUPPORT) 784778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.SHORTCUT_SUPPORT) 785778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.PHOTO_SUPPORT) 786f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 7877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 7889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 7899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 7909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 7919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 7929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 7939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 7942526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 7952526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 796bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 797bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 798bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 799bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 80051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 801f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 8021129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 8031129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 8042526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 8052526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 806f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 807f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 8084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 8094f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 810a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 811d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 812d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 813a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA); 814a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES); 8153653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 8163653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 8172d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 8182d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 819a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO); 820c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); 8215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 8225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 8232149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA); 8245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 8252149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", 8262149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov CONTACTS_LOOKUP_ID_DATA); 827a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", 828a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ENTITIES); 829a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", 830a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ID_ENTITIES); 831f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 83242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 83342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 8345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 835ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 836ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 8375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 8383653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 8395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 8405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 8415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 84246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 84346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 84446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 845b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 8464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 8474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 848ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 84948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 8505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 851ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 8524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 85348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 8541dac83b8fa58944acfd00f44e717a7dddc659d2dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup", EMAILS_LOOKUP); 8555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 8565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 8574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 858ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 85948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 8601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 861ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 862ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 863ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 864ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 86535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 866b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 867b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 86835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 869a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 870b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 871b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 872b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 873b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 8744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 875eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 876eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 87782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 87882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 8791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 880c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 881c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 882c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 883c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 8842d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 885c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 886c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 8871b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 8881b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 8891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 8901b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 8911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 8921b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 8931b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 8941b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 89509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 89609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 897d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 898d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories", DIRECTORIES); 899d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories/#", DIRECTORIES_ID); 9007a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 9017a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "complete_name", COMPLETE_NAME); 90219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 90319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 904d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static class DirectoryInfo { 905d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String authority; 906d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountName; 907d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountType; 908d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 909d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 910d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 911d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Cached information about contact directories. 912d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 9134458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private HashMap<String, DirectoryInfo> mDirectoryCache = new HashMap<String, DirectoryInfo>(); 9144458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private boolean mDirectoryCacheValid = false; 915d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 9163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 917ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 918ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 919ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 920e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov public static class GroupIdCacheEntry { 921ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 922ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 923ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 924ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 925ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 926a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 927e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 928e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 929e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // is a list of groups with this group id. 930e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 931e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov 9323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 933b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 93431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 9354097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 936f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 937315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 938622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 939622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 94072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private ContactDirectoryManager mContactDirectoryManager; 941622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 942f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 943a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 944d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 945a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 94620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 94773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 94820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 94909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 9503826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private boolean mProviderStatusUpdateNeeded; 95109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 95215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mReadAccessLatch; 95315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mWriteAccessLatch; 95415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private boolean mAccountUpdateListenerRegistered; 955bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private boolean mOkToOpenAccess = true; 95673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 957d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private TransactionContext mTransactionContext = new TransactionContext(); 958de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 9591a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 9601a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 96181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 96281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 9634cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 9643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private int mContactsAccountCount; 965d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 966bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private HandlerThread mBackgroundThread; 967bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private Handler mBackgroundHandler; 968bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 9694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 9704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 971de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 972ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 973ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 974ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 975ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 976ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 977ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 978ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 97935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 980ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 98115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov StrictMode.setThreadPolicy( 98215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); 98315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 984b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 98572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager = new ContactDirectoryManager(this); 986a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 98765ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 988bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // The provider is closed for business until fully initialized 98915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = new CountDownLatch(1); 99015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = new CountDownLatch(1); 99172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 992bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread = new HandlerThread("ContactsProviderWorker", 993bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Process.THREAD_PRIORITY_BACKGROUND); 994bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread.start(); 995bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { 996bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 997bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void handleMessage(Message msg) { 998bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov performBackgroundTask(msg.what, msg.obj); 999bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1000bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov }; 10012a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 100215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_INITIALIZE); 1003bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1004bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 1005bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_LOCALE); 1006bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM); 1007bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_PROVIDER_STATUS); 100815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_OPEN_WRITE_ACCESS); 10093826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 101049d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov return true; 10114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 10124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1013767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 101451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 101551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 101604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 101715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 101815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 10194cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 102004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov mNameSplitter = mDbHelper.createNameSplitter(); 10214cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 10224cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 102351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mCommonNicknameCache = new CommonNicknameCache(mDbHelper.getReadableDatabase()); 1024cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 10255b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper, 102615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 10275b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 10285b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 1029bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 1030bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1031bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, 1032bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov new DataRowHandlerForEmail(mDbHelper, mContactAggregator)); 1033bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 1034bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov new DataRowHandlerForCommonDataKind(mDbHelper, mContactAggregator, 1035bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 1036bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, 1037bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov new DataRowHandlerForCommonDataKind(mDbHelper, mContactAggregator, 1038bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, 1039bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov StructuredPostal.LABEL)); 1040bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, 1041bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov new DataRowHandlerForOrganization(mDbHelper, mContactAggregator)); 1042bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, 1043bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov new DataRowHandlerForPhoneNumber(mDbHelper, mContactAggregator)); 1044bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, 1045bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov new DataRowHandlerForNickname(mDbHelper, mContactAggregator)); 1046bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 1047bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov new DataRowHandlerForStructuredName(mDbHelper, mContactAggregator, 1048bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mNameSplitter, mNameLookupBuilder)); 1049bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 1050bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov new DataRowHandlerForStructuredPostal(mDbHelper, mContactAggregator, 1051bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mPostalSplitter)); 1052bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, 1053bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov new DataRowHandlerForGroupMembership(mDbHelper, mContactAggregator, 1054bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mGroupIdCache)); 1055bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, 1056bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov new DataRowHandlerForPhoto(mDbHelper, mContactAggregator)); 1057bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1058bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1059bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /** 1060bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Visible for testing. 1061bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov */ 1062bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 1063bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return new PhotoPriorityResolver(context); 1064bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1065bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1066bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task) { 1067bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendEmptyMessage(task); 1068bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1069bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1070bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task, Object arg) { 1071bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(task, arg)); 1072bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1073bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1074bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void performBackgroundTask(int task, Object arg) { 1075bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov switch (task) { 107615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_INITIALIZE: { 107715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov initForDefaultLocale(); 107815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch.countDown(); 107915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = null; 108015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov break; 108115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 108215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 108315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_OPEN_WRITE_ACCESS: { 1084bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (mOkToOpenAccess) { 108515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch.countDown(); 108615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = null; 1087bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1088bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1089bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1090bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1091bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS: { 1092bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1093bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov importLegacyContactsInBackground(); 1094bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1095bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1096bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1097bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1098bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_ACCOUNTS: { 109915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 110015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (!mAccountUpdateListenerRegistered) { 110115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov AccountManager.get(context).addOnAccountsUpdatedListener(this, null, false); 110215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mAccountUpdateListenerRegistered = true; 110315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 110415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 110515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Account[] accounts = AccountManager.get(context).getAccounts(); 1106bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean accountsChanged = updateAccountsInBackground(accounts); 1107bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateContactsAccountCount(accounts); 1108bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateDirectoriesInBackground(accountsChanged); 1109bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1110bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1111bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1112bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_LOCALE: { 1113bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateLocaleInBackground(); 1114bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1115bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1116bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1117fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov case BACKGROUND_TASK_CHANGE_LOCALE: { 1118fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov changeLocaleInBackground(); 1119fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov break; 1120fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1121fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1122bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM: { 1123bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isAggregationUpgradeNeeded()) { 1124bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov upgradeAggregationAlgorithmInBackground(); 1125bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1126bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1127bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1128bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1129bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_PROVIDER_STATUS: { 1130bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateProviderStatus(); 1131bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1132bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1133bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1134bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_DIRECTORIES: { 1135bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (arg != null) { 1136bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.onPackageChanged((String) arg); 1137bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1138bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1139bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1140bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 11414cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 11424cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 114353fac8f99f3884c372c907a76766d27fa9e1d95fDmitri Plotnikov public void onLocaleChanged() { 11443826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 11453826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 11464f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov return; 11474f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov } 11484f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 1149fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_CHANGE_LOCALE); 11504cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 115151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 115251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 115351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 115451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 115551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 115651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 115751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 115851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 1159bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateLocaleInBackground() { 1160f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 1161f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 1162f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 1163f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 1164f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 1165f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 116651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 116751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 116851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 116951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 117051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 117151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 117251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 117351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 117451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 1175bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDbHelper.setLocale(this, currentLocale); 1176bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).apply(); 1177bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov setProviderStatus(providerStatus); 1178bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 117951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1180fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov /** 1181fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov * Reinitializes the provider for a new locale. 1182fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov */ 1183fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private void changeLocaleInBackground() { 1184fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Re-initializing the provider without stopping it. 1185fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Locking the database will prevent inserts/updates/deletes from 1186fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // running at the same time, but queries may still be running 1187fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // on other threads. Those queries may return inconsistent results. 1188fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getWritableDatabase(); 1189fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.beginTransaction(); 1190fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov try { 1191fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov initForDefaultLocale(); 1192fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.setTransactionSuccessful(); 1193fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } finally { 1194fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.endTransaction(); 1195fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1196fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1197fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov updateLocaleInBackground(); 1198fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1199fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1200bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateDirectoriesInBackground(boolean rescan) { 1201bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanAllPackages(rescan); 120251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 120351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 12043826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateProviderStatus() { 12053826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 12063826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 12073826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return; 12083826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 12093826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 12103826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mContactsAccountCount == 0 121149d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov && DatabaseUtils.queryNumEntries(mDbHelper.getReadableDatabase(), 121249d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Tables.CONTACTS, null) == 0) { 12133826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 12143826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } else { 12153826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 12163826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 12173826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 12183826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 121931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1220de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1221b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1222b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 122331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 122431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1225013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1226013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1227013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1228013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 12295df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov /* package */ NameLookupBuilder getNameLookupBuilder() { 12305df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov return mNameLookupBuilder; 12315df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov } 12325df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov 12335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 1234ed78fd6df5e9f3a2d572162e5d374d1f4a625bddDmitri Plotnikov public ContactDirectoryManager getContactDirectoryManagerForTest() { 123572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return mContactDirectoryManager; 123672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 123772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 123872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 12395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 12405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 12415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 12425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 12433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 1244b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 1245b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 12463d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 12473d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1248568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1249568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1250568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1251568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1252568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1253bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Imports legacy contacts as a background task. 1254568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1255bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private void importLegacyContactsInBackground() { 1256bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 1257bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 1258568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1259bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 1260bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDbHelper.setLocale(this, mCurrentLocale); 1261bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 1262568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1263bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1264bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (importLegacyContacts(importer)) { 1265bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportSuccess(); 1266bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } else { 1267bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportFailure(); 1268bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1269568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1270568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1271bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1272bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 1273bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1274bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 1275bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1276bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 1277bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 1278bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1279b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 1280b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDbHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 1281b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 1282bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 1283bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 1284bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1285bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1286bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1287bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 1288bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1289bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 1290bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 1291bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1292bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 1293bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1294bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 1295bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 1296bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 1297bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 1298bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 1299bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 1300bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 1301bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 1302bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 1303bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1304bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 1305bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1306bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 1307bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 1308bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1309bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // Do not let any database changes until this issue is resolved. 1310bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mOkToOpenAccess = false; 13113d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 13123d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 13133d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1314568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 13150e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 13163d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 13173d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 1318bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 1319bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1320bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1321bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 1322bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 1323bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 13243d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 13253d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 13263d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1327bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 1328bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 13293d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 13303d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1331a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1332a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1333a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1334a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1335b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 13363826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS; 1337a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1338a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1339568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 134015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov * During intialization, this content provider will 1341568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1342568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1343568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1344568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1345568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 134615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private void waitForAccess(CountDownLatch latch) { 134715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (latch == null) { 134815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 134915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 135015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 135115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov while (true) { 135215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov try { 135315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov latch.await(); 135415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 135515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } catch (InterruptedException e) { 135615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Thread.currentThread().interrupt(); 1357ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1358568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1359568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1360568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1361568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1362568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 136315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1364568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1365568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1366568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1367568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1368568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 136915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (mWriteAccessLatch != null) { 1370bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 1371bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 1372bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 1373bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 1374bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (match == PROVIDER_STATUS) { 1375bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 1376bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 1377bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1378bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 1379bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 1380bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 1381bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1382bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1383bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 138415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1385568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1386568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1387568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1388568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1389568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 139015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1391568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1392568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1393568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1394568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1395568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1396568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 139715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1398568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1399568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1400568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 14014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1402285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1403bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1404b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1405b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1406285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 14071ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1408d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.clear(); 1409b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1410b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1411285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1412285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1413285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 14141129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 1415bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1416b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1417b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1418285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1419b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 14201ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 14211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 14221a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 1423b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 14241a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 14253826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 14263826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatusUpdateNeeded) { 14273826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 14283826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = false; 14293826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 1430b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1431b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1432b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1433bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1434b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1435b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 14361129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 1437d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov for (long rawContactId : mTransactionContext.getInsertedRawContactIds()) { 14387e2635fa663312adb2bc9d04f50a6bb54c6cc5f4Dmitri Plotnikov mContactAggregator.updateRawContactDisplayName(mDb, rawContactId); 1439d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mContactAggregator.onRawContactInsert(mDb, rawContactId); 1440285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1441b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1442d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov Set<Long> dirtyRawContacts = mTransactionContext.getDirtyRawContactIds(); 1443d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!dirtyRawContacts.isEmpty()) { 1444a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 1445a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 1446d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, dirtyRawContacts); 1447a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 1448a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 1449a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 1450a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1451d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov Set<Long> updatedRawContacts = mTransactionContext.getUpdatedRawContactIds(); 1452d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!updatedRawContacts.isEmpty()) { 1453a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 1454a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 1455d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, updatedRawContacts); 1456a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 1457a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 1458b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1459b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1460d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov for (Map.Entry<Long, Object> entry : mTransactionContext.getUpdatedSyncStates()) { 1461b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 14629d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana if (mDbHelper.getSyncState().update(mDb, id, entry.getValue()) <= 0) { 14639d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 14649d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 14659d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 1466b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1467b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1468d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.clear(); 1469b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1470b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1471a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 1472a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 1473a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 1474a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 1475d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private void appendIds(StringBuilder sb, Set<Long> ids) { 1476b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 1477a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 1478b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1479a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1480a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 1481285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1482285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1483285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1484cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 148581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 148681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 148781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 148881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 148981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 149081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 149181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 1492cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 1493568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 149451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 14953826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != status) { 14963826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = status; 14973826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov getContext().getContentResolver().notifyChange(ProviderStatus.CONTENT_URI, null, false); 14983826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 149951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 150051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 15013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 15023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 15033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 1504f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov handler = new DataRowHandlerForCustomMimetype(mDbHelper, mContactAggregator, mimeType); 15053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 15063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 15083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1511de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 1512bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 15131129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 1514b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1515f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1516f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 1517f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 1518f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1519a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 1520a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 152135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1522a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 152335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 1524b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 152535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 152635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1527d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1528d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 15296bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 15306bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 15316bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 15325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 1533dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana id = insertRawContact(uri, values, callerIsSyncAdapter); 1534f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1535a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1536a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1537a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 15385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 15395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 1540f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1541f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1542a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1543a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1544a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1545a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 1546f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1547f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1548a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1549a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1550a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1551ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1552f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 1553f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1554ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1555ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1556ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1557eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 15585aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 155943880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 1560eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 1561eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 1562eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 156382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 156482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 15651f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 15661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 15671f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1568a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 156981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 1570f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 1571a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1572a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 15737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 15747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 15757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 15767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1577de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 1578a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1579a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1580a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1581e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 1582e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 1583e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 1584e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 1585e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 1586e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 1587e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 1588e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 1589e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 1590e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 1591e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 1592e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 1593e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 15947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 1595e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 1596f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 1597f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 1598e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 1599f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1600f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 1601f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 1602e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 1603e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 1604e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1605e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 1606e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 1607fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 1608fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 1609e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 1610e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1611e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 1612e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 1613e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 1614e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 1615e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1616e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 1617e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 1618e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 1619e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 1620e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 1621fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 1622fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 1623e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 1624e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 1625e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 1626f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 1627f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 1628e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 1629f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 1630f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 1631e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 1632e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 1633f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 1634f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1635e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 1636f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 1637f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 1638f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 1639f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 1640035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1641f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1642e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 16437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 16447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 16457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 1646d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 16476bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 16486bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 16496bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 16506bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1651d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 1652de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 16536bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 16546bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 16556bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 1656a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 1657a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1658f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 1659f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 1660dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param callerIsSyncAdapter 1661a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1662a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1663dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private long insertRawContact(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 1664f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 1665f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 1666f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 1667f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1668e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 16697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 16703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 16713d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 1672f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 16733d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 16743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1675f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 1676f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 1677f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 1678f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 1679f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 1680f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId, aggregationMode); 1681285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1682285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 1683d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.rawContactInserted(rawContactId, account); 1684f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1685dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 1686dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 1687dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long starred = values.getAsLong(RawContacts.STARRED); 1688dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (starred != null && starred != 0) { 1689dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred != 0); 1690dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1691dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1692dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 16933826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 1694023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 1695a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1696a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1697dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void addAutoAddMembership(long rawContactId) { 1698dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID, 1699dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 1700dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 1701dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 1702dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1703dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1704dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1705dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private Long findGroupByRawContactId(String selection, long rawContactId) { 1706dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.GROUPS + "," + Tables.RAW_CONTACTS, PROJECTION_GROUP_ID, 1707dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, 1708dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}, 1709dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana null /* groupBy */, null /* having */, null /* orderBy */); 1710dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 1711dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 1712dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return c.getLong(0); 1713dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1714dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return null; 1715dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 1716dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 1717dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1718dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1719dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1720dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateFavoritesMembership(long rawContactId, boolean isStarred) { 1721dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID, 1722dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 1723dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 1724dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (isStarred) { 1725dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 1726dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 1727dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana deleteDataGroupMembership(rawContactId, groupId); 1728dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1729dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1730dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1731dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1732dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void insertDataGroupMembership(long rawContactId, long groupId) { 1733dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues groupMembershipValues = new ContentValues(); 1734dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.GROUP_ROW_ID, groupId); 1735dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 1736dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(DataColumns.MIMETYPE_ID, 1737dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDbHelper.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 1738dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.insert(Tables.DATA, null, groupMembershipValues); 1739dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1740dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1741dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void deleteDataGroupMembership(long rawContactId, long groupId) { 1742dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final String[] selectionArgs = { 1743dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(mDbHelper.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)), 1744dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(groupId), 1745dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(rawContactId)}; 1746dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs); 1747dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1748dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1749a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1750a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 1751a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1752a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1753a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1754a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1755f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 1756a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 1757de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 1758de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 175967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 1760de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 176120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1762de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 1763de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 1764de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 1765b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 1766de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 1767de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 1768508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 1769de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 1770de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 1771de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 1772de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 1773de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 17744097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1775b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 1776de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 1777a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1778a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 1779d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov id = rowHandler.insert(mDb, mTransactionContext, rawContactId, mValues); 1780f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1781d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.markRawContactDirty(rawContactId); 1782a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1783d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.rawContactUpdated(rawContactId); 1784a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 17854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 17864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1787ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 17887e2635fa663312adb2bc9d04f50a6bb54c6cc5f4Dmitri Plotnikov mContactAggregator.updateRawContactDisplayName(db, rawContactId); 1789d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 1790d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 17919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 179220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 179320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 1794f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 179520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 179620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1797de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 1798de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 1799f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, 1800f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 1801de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 1802de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 1803f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID); 1804f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 1805a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 1806d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov count += rowHandler.delete(mDb, mTransactionContext, c); 1807f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1808d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.markRawContactDirty(rawContactId); 180988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 181020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 181120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 1812de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 181320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 181420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 181520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 181620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 181720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 181888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 181988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 182088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 182120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 1822f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 182388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 182488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 18254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 1826f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, Data._ID + "=?", 18274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 1828f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 182920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 183020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 183120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 183220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 183320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1834f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 183520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 183620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 183720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 183820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 183920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 184020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 184120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 184220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 184320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 18447a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 184520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 184620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 184720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1848a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 1849d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov return rowHandler.delete(mDb, mTransactionContext, c); 185020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 185120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 185220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 185320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 185420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 185520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 1856ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 1857ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 1858f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 1859f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 1860f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 1861f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1862e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 1863ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1864ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 1865f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 186667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 1867f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 186867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 1869f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 1870ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1871dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final boolean isFavoritesGroup = mValues.getAsLong(Groups.FAVORITES) != null 1872dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ? mValues.getAsLong(Groups.FAVORITES) != 0 1873dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana : false; 1874dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1875f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1876f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 187773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 187873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1879f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 1880ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 1881dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && isFavoritesGroup) { 1882dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // add all starred raw contacts to this group 1883dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String selection; 1884dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs; 1885dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (account == null) { 1886dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + " IS NULL AND " 1887dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContacts.ACCOUNT_TYPE + " IS NULL"; 1888dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = null; 1889dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 1890dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + "=? AND " 1891dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContacts.ACCOUNT_TYPE + "=?"; 1892dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = new String[]{account.name, account.type}; 1893dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1894dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, 1895dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{RawContacts._ID, RawContacts.STARRED}, 1896dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, selectionArgs, null, null, null); 1897892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov try { 1898892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov while (c.moveToNext()) { 1899892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (c.getLong(1) != 0) { 1900892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov final long rawContactId = c.getLong(0); 1901892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov insertDataGroupMembership(rawContactId, result); 1902d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.markRawContactDirty(rawContactId); 1903892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 1904dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1905892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } finally { 1906892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov c.close(); 1907dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1908dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1909dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1910f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 19111a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 1912ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 1913ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 1914ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 1915ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1916ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 19175aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 1918e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 19195aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 19201a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 19211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 1922e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 19231a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 1924e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 1925e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 1926e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 1927ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 192882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 19291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 193082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 193182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 19320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 19334dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 19344dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 19350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 193682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 19374dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 19384dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 19394dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 19404dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 19411f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 19421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1943dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 1944dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 194582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 1946f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 19472526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 1948dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 1949dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 1950dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 19512526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 19522526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 19531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 1954dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 1955dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 19560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 19570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 19580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 19590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 1960dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 1961dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 1962dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 19632a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov String mimeTypeIdIm = String.valueOf(mDbHelper.getMimeTypeIdForIm()); 1964dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 19652a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov String mimeTypeIdEmail = String.valueOf(mDbHelper.getMimeTypeIdForEmail()); 1966f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 1967f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 1968f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 1969f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 1970f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 1971f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 1972f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 19732526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 19742526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 19752526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 19762526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 19772526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 19782526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 19792526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 19802526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 1981dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 19822526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 19832526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 1984dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 19852526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 19862526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 1987dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 19882526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 19892526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 19902526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 19912526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 19922526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 19932526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 1994dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 19952526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 19962526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 1997dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 1998dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 19991f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 200082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 20012526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 20022526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 2003dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 200470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 2005f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 200670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 20071f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 20081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2009de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 20102526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 20114394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID); 20121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 201367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 20145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2015e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 20161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 20171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 20181f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 20191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 202131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 202231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 202331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 20241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 202682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2027a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2028a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2029a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2030a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2031a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2032a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2033a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 203482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2035a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2036a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 203782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 203882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 203982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 204082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 204182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2042a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 204382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 204482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 2045aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori mValues.put(StatusUpdates.CHAT_CAPABILITY, 2046aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori values.getAsString(StatusUpdates.CHAT_CAPABILITY)); 20471f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2048a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2049a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2050a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2051e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 20520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 205382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 205482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 20550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 20560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 20570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 20580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 20590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 20600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 20610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 20620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 20630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 20640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 20650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 20660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2067a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 206878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.deleteStatusUpdate(dataId); 206982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 207082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 207178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.replaceStatusUpdate(dataId, timestamp, status, resPackage, iconResource, 207278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov labelResource); 2073a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 207478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.insertStatusUpdate(dataId, status, resPackage, iconResource, 207578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov labelResource); 2076e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2077e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2078bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2079a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2080f4015ab9ab7c26b766b5331fbf6655b8c54877eaDmitri Plotnikov mContactAggregator.updateLastStatusUpdateId(contactId); 2081a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2082a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2083a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 20841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20851f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 20864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2087de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2088bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2089b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2090b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2091b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2092f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2093f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2094508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2095508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 209635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2097b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 209835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2099b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2100b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2101b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2102b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2103b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2104b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2105cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2106cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2107cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2108cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2109cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2110d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2111d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2112dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 21136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 21146bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 21159fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 21162e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 21172e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 21182e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 2119fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2120fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 21212e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 21222e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 21232e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 2124dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 21252e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 21262e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 21279fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 21289fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 21299fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 21309fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 21319fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 21329fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 2133a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 21349fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 21359fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 21369fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 21379fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 21389fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 21399fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 21409fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 21419fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 214260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 21439fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 21449fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 21459fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann Cursor c = query(db, lookupQb, null, selection, args, null, null, null); 21469fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 21479fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 21489fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 2149dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 21509fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 21519fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 21529fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 21539fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 21549fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 21559fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 21569fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 21579fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 21589fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 21599fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 21602971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 21612971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 2162fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, 2163fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 2164e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 21652971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 21662971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 21672971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2168fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 2169fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 2170fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 21712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 21722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 21732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 21742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 21752971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 21762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 21772971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 21785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 21792971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2180fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return deleteRawContact(rawContactId, mDbHelper.getContactId(rawContactId), 2181fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 2182508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2183508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 218420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2185f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2186944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2187f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 218820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 218920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 219048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 219148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 219248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 219348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2194508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2195f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 21964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 21974da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 2198ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2199ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2200ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2201f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 22025aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 22032971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 22042971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 22052971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 22062971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 22072971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2208e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 22092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 22102971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 22115aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 22122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 22132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 22142971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 22152971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 221681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2217f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 221881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 22192971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2220508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2221508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2222eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 222343880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2224e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 2225eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2226eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 222782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 22280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 22291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 22301f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 223181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 223281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 22333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 223481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2235508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 22364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 22381c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 2239ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 2240b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 224194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2242de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 224394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 224494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 224594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 224694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2247f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2248de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 224994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 225094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 225194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2252f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2253de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 225494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 225594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 22561a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 225794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 225894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 225994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 22605aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2261e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 22621a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2263e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2264e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2265e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2266dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int deleteContact(long contactId, boolean callerIsSyncAdapter) { 226796b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 2268cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 226996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 227096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 2271cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2272cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2273cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2274dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 2275cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2276cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2277cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2278cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2279cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 22803826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 22813826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2282cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2283cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2284cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2285fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 22863389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 22873826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 22883826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2289f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 229014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2291fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov int count = mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 2292fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForContact(mDb, contactId); 2293fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 229433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2295b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 2296dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 229733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 229833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 229933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 23000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 23019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 23029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 23039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 23049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 23059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 23069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 23079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 23089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 23090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 23100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2311dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) { 231281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 231381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 2314cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 2315cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 2316cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2317cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2318cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2319cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2320dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues, callerIsSyncAdapter); 2321cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2322cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 23234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2324de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2325de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 2326bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2327b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2328b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2329b5a4add17815167d20a90645779df34cdf45280dFred Quintana 233035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 233100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 233200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 2333b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 2334b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 23351129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 2336d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.syncStateUpdated(rowId, data); 2337b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 2338b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2339b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2340f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2341f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 234200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 234335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2344b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2345b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 2346b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2347b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 2348b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 2349b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2350b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2351b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2352b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2353b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 2354b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 235535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2356d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2357dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 235800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 235900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 236000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2361d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2362dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter); 2363c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2364c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2365c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 23662e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 23672e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 23682e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 23692e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 23702e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 2371fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2372fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 23732e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 23742e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 23752e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 2376dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(contactId, values, callerIsSyncAdapter); 23772e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 23782e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 23792e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 23807d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 23817d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 23827d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 23837d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 23847d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 23857d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 23867d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 23877d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 23887d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 23897d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 239020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2391944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2392f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 239381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2394f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 239581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 239620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 239720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2398c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 239948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 240048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 240148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 240248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2403f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 240481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2405f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 240681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 240700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 240800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 24097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 24105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 24115ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 2412dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, selection, selectionArgs, callerIsSyncAdapter); 24137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 24147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 24165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 241733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 24184529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 24194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 24204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 2421dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND(" + selection + ")", selectionArgs, 2422dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 24234529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 24244da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 2425dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1, 2426dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 24274529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 24287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 24297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2431ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 24325aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 2433f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 243481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2435f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 243681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2437ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2438ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2439ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2440ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2441ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 24424da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 24434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 244473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 24455aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 24465aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 244781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2448f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 244981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2450ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2451ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2452ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2453127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 2454de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 2455b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2456b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2457b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2458eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 2459e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 2460e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 246143880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2462eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2463eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2464eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 24659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 24669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 24679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 24689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 24699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 247072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case DIRECTORIES: { 2471bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanPackagesByUid(Binder.getCallingUid()); 247272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov count = 1; 2473d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 2474d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 2475d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 247681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 247781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2478f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 247981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 248000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 248100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 248200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 24834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 24844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 24859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 24869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 24879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 24889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 24899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 24909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 24919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 24929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 24939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 24949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 24959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 24969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 24979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 24989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 24999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 25009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 25019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 25029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 25039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 25059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 25069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 25079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 25109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 25119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 25129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 25139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 25149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 25159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 25169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 25179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 25189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 25219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 25229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 25239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 25249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 25259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 25269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 25279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 25289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 25299705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 25309705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 25319705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 25329705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 25339705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25349705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25359705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 25369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 25379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 25389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 2539aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.CHAT_CAPABILITY, values, 2540aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori StatusUpdates.CHAT_CAPABILITY); 25419705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 25429705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25445aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 2545f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 254673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2547ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 2548ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 254973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 2550f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 255173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 255273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 255373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 255473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 255573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 255673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 255773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 255873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2559ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 25601a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 25611a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 256294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 25636ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 25641129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 25656ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 2566e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 25676ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 25686ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 25696ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 25706ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 25716ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 25726ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 25736ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 25746ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 25756ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 2576ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 25776ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 25786ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 25796ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 25806ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 25816ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 25826ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 25836ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 25846ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 258594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 258694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 258794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2588b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 2589b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 2590e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 25911a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 25921a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2593e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2594e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2595e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2596e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2597dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs, 2598dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 25994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 26004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 26014529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 26024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 260373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 260497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 260597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 260697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0"); 260797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 260897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 26094529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 2610b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 261151bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 26124529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 26134529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 26144529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 26154529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 2616dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContact(rawContactId, values, callerIsSyncAdapter); 26174529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 26184529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26194529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 26204529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 26214529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26224529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 26234529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 26244529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26254529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 2626dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContact(long rawContactId, ContentValues values, 2627dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 262896b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 262996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 263019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 263119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 263219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 2633ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 2634ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 263519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 263619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 263796b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1, null, null, null); 263819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 263919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 264019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 2641ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 2642ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 264319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 264419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 264519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 264619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 264719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 264819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 264919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 2650f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 265196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker int count = mDb.update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 26525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 2653f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 2654f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 2655f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 2656f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 2657f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 2658f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 265969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode, false); 2660f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2661f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2662433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 2663dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 2664dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 2665dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana values.getAsLong(RawContacts.STARRED) != 0); 2666dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 26674529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 2668dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2669dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then update the 2670dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // favorites group membership based on whether or not this contact is starred. 2671dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // If it is starred, add a group membership, if one doesn't already exist 2672dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // otherwise delete any matching group memberships. 2673dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 2674dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean starred = 0 != DatabaseUtils.longForQuery(mDb, 2675dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SELECTION_STARRED_FROM_RAW_CONTACTS, 2676dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}); 2677dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred); 2678dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2679dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2680dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2681dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then add a 2682dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // group membership to the group marked as AutoAdd, if any. 2683dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 2684dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 2685433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 2686dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2687285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 26882b7a632bba423357ae5641f94da6a2f71afc523bDmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(mDb, rawContactId); 2689285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2690f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 2691f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 2692f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 2693f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 2694f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 269578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.resetNameVerifiedForOtherRawContacts(rawContactId); 2696f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 2697f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(mDb, rawContactId); 2698f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 269919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 2700d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.rawContactInserted(rawContactId, 2701d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov new Account(accountName, accountType)); 270219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 27035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 27045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 270533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 270633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 2707321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 2708f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 270920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 271020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 271120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 27125ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 271320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 271420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 271520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 271620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 271720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2718b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 271920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 272020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 272197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 272297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 272397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov Data.IS_READ_ONLY + "=0"); 272497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 272597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 2726653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 272720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2728653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2729653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 2730f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(uri, DataRowHandler.DataUpdateQuery.COLUMNS, 2731f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 2732653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 2733653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 2734f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 273520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2736653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 2737653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 273820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 273920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2740653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 274120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 274220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2743f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 2744653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 2745653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 2746321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2747653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 2748f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String mimeType = c.getString(DataRowHandler.DataUpdateQuery.MIMETYPE); 2749a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2750d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (rowHandler.update(mDb, mTransactionContext, values, c, callerIsSyncAdapter)) { 2751813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 1; 2752813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } else { 2753813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 0; 2754a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2755321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2756321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 27578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 2758dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 27598c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 2760b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 27618c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 27628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 27638c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 27648c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 27658c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 2766dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateContactOptions(contactId, values, callerIsSyncAdapter); 27678c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 27688c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 27698c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 27708c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 27718c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 27728c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 27738c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 27748c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 27758c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 2776dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateContactOptions(long contactId, ContentValues values, 2777dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 2778d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 27798c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 2780b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 2781d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 2782b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 2783d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 2784b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 2785d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 2786b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 2787d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 2788b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 2789d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 2790d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2791d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 27928c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 2793d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 2794d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2795d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 27968c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 2797c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 27988c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2799c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 2800c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 28014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 280297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?" 280397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov + " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1); 28048c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 2805dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) { 2806dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 2807dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?", 2808dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null, null, null); 2809dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 2810dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (cursor.moveToNext()) { 2811dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long rawContactId = cursor.getLong(0); 2812dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 2813dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.getAsLong(RawContacts.STARRED) != 0); 2814dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2815dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2816dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana cursor.close(); 2817dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2818dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2819dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 28208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 28218c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 28228c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 2823b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 28248c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 2825b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 28268c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 2827b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 28288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 2829b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 28308c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 2831b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 28328c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 28338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 28349b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori int rslt = mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 28356e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 28369b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 28379b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 28389b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 28399b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 28409b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 28419b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 2842f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2843d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2844127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 2845127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 28460c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 28470c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 284880c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 2849ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId1; 2850ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId2; 28510c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 28520c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 28530c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 28540c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 28550c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 28560c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 2857b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2858127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 28590c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 28604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 28614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 28620c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 28634da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 28644da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 28650c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 28666bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 28676bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 28680c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 28690c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 28700c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 28710c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 2872127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2873127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 28743389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 287569cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1, 287669cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 287769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2, 287869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 2879dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 28800dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1); 28810dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2); 2882127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2883127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 2884127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 2885127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 2886b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2887b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 288870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 2889bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 28903826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 28913826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2892bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected boolean updateAccountsInBackground(Account[] accounts) { 2893f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 2894e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov boolean accountsChanged = false; 2895627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 289649d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 289770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 289870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 2899dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana findValidAccounts(existingAccounts); 2900743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 2901743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // Add a row to the ACCOUNTS table for each new account 2902743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 2903743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov if (!existingAccounts.contains(account)) { 2904e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 2905743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 2906743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov + ", " + RawContacts.ACCOUNT_TYPE + ") VALUES (?, ?)", 2907743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov new String[] {account.name, account.type}); 2908743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 2909743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 291048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 2911627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 2912743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // in the accountsToDelete set will be extra accounts whose data must be deleted. 2913627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 2914627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 2915627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 291670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 291770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 291833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov if (!accountsToDelete.isEmpty()) { 2919e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 2920e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov for (Account account : accountsToDelete) { 2921e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov Log.d(TAG, "removing data for removed account " + account); 2922e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 2923e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 2924e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 2925e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 2926e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 2927e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 2928e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 2929e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 2930e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "SELECT " + RawContacts._ID + 2931e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 2932e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 2933e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 2934e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 2935e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 2936e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 2937e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 2938e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 2939e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 2940e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 2941e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 2942e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 2943e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 2944e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 2945e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + "=?", params); 2946d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mDb.execSQL( 2947d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov "DELETE FROM " + Tables.DIRECTORIES + 2948d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " WHERE " + Directory.ACCOUNT_NAME + "=?" + 2949d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " AND " + Directory.ACCOUNT_TYPE + "=?", params); 29504458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov resetDirectoryCache(); 2951e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 2952e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 295333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 295433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 2955e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov // names or photos. If so, fix up those contacts. 295633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 295733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Cursor cursor = mDb.rawQuery("SELECT " + Contacts._ID + 295833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 295933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 296069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 296169cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 296269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 296333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 296433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 296569cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 296669cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 296733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 296833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 296933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 297033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 297133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 297233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 297333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 297433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 297533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 297633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 297733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 2978e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDbHelper.updateAllVisible(); 297933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 298033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 2981e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (accountsChanged) { 2982e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 2983e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 298470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 298570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 298670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 298770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 298873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 29893826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 29903826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (accountsChanged) { 29913826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateContactsAccountCount(accounts); 29923826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 29933826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 29943826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2995afb84050536a4472c13efc0e996d31132d254605Dmitri Plotnikov return accountsChanged; 299670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 2997619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 29983826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateContactsAccountCount(Account[] accounts) { 29993826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov int count = 0; 30003826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov for (Account account : accounts) { 30013826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (isContactsAccount(account)) { 30023826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov count++; 30033826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30043826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30053826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mContactsAccountCount = count; 30063826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30073826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 30083826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov protected boolean isContactsAccount(Account account) { 30093826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov final IContentService cs = ContentResolver.getContentService(); 30103826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov try { 30113826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return cs.getIsSyncable(account, ContactsContract.AUTHORITY) > 0; 30123826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } catch (RemoteException e) { 30133826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov Log.e(TAG, "Cannot obtain sync flag for account: " + account, e); 30143826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return false; 30153826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30163826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30173826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 301872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPackageChanged(String packageName) { 3019bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_DIRECTORIES, packageName); 3020d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3021d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3022619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3023627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 3024627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 3025dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void findValidAccounts(Set<Account> validAccounts) { 3026743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov Cursor c = mDb.rawQuery( 3027743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "SELECT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 3028743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " FROM " + Tables.ACCOUNTS, null); 3029627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 3030627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 3031dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!c.isNull(0) || !c.isNull(1)) { 3032627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 3033627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3034627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3035627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 3036627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 3037627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3038627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3039627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 30404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 30414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 30424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 304315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 304415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mReadAccessLatch); 304515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 3046d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY); 3047385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directory == null) { 3048385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov return queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1); 3049385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directory.equals("0")) { 3050385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov return queryLocal(uri, projection, selection, selectionArgs, sortOrder, 3051385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov Directory.DEFAULT); 3052d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } else if (directory.equals("1")) { 3053385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov return queryLocal(uri, projection, selection, selectionArgs, sortOrder, 3054385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov Directory.LOCAL_INVISIBLE); 3055d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3056d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3057d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryInfo directoryInfo = getDirectoryAuthority(directory); 3058d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo == null) { 3059a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov Log.e(TAG, "Invalid directory ID: " + uri); 3060a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov return null; 3061d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3062d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3063d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Builder builder = new Uri.Builder(); 3064d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.scheme(ContentResolver.SCHEME_CONTENT); 3065d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.authority(directoryInfo.authority); 3066d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.encodedPath(uri.getEncodedPath()); 3067d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountName != null) { 3068d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, directoryInfo.accountName); 3069d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3070d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountType != null) { 3071d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, directoryInfo.accountType); 3072d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 30732e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 30742e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limit = getLimit(uri); 30752e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov if (limit != null) { 30762e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov builder.appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, limit); 30772e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov } 30782e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 3079d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Uri directoryUri = builder.build(); 308009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 308109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (projection == null) { 308209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov projection = getDefaultProjection(uri); 308309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 308409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 3085332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov Cursor cursor = getContext().getContentResolver().query(directoryUri, projection, selection, 3086d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs, sortOrder); 3087332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov while (cursor instanceof CursorWrapper) { 3088332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov cursor = ((CursorWrapper)cursor).getWrappedCursor(); 3089332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov } 3090332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov return cursor; 3091d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3092d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3093d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final class DirectoryQuery { 3094d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 3095d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory._ID, 3096d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.DIRECTORY_AUTHORITY, 3097d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_NAME, 3098d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_TYPE 3099d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov }; 3100d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3101d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int DIRECTORY_ID = 0; 3102d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int AUTHORITY = 1; 3103d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_NAME = 2; 3104d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_TYPE = 3; 3105d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3106d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3107d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 3108d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Reads and caches directory information for the database. 3109d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 3110d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private DirectoryInfo getDirectoryAuthority(String directoryId) { 31114458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized (mDirectoryCache) { 31124458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (!mDirectoryCacheValid) { 31134458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.clear(); 311449d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 311549d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Cursor cursor = db.query(Tables.DIRECTORIES, 31164458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryQuery.COLUMNS, 31174458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov null, null, null, null, null); 31184458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov try { 31194458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov while (cursor.moveToNext()) { 31204458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryInfo info = new DirectoryInfo(); 31214458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov String id = cursor.getString(DirectoryQuery.DIRECTORY_ID); 31224458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.authority = cursor.getString(DirectoryQuery.AUTHORITY); 31234458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME); 31244458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE); 31254458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.put(id, info); 31264458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 31274458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } finally { 31284458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov cursor.close(); 3129d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 31304458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = true; 3131d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3132d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 31334458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov return mDirectoryCache.get(directoryId); 31344458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 3135d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3136d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 313772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void resetDirectoryCache() { 31384458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized(mDirectoryCache) { 31394458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = false; 31404458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 314172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 314272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 3143d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public Cursor queryLocal(Uri uri, String[] projection, String selection, String[] selectionArgs, 3144385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov String sortOrder, long directoryId) { 3145bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3146bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3147bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 31480b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 3149b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 315035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3151d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 31521f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3153c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3154c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3155619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3156619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3157a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 31584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 315935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3160b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 316135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 316235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3163d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3164763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3165385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov appendLocalDirectorySelectionIfNeeded(qb, directoryId); 3166619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3167619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3168619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3169d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 31704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3171763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 31724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 31734da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 31746bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 31756bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 31766bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 31775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 31785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 31795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 31805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 31815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 3182fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3183fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 31845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 3185a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 31865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 31875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 31885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 31895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3190763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 3191a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3192a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 3193a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 3194a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 3195a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 31965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 31975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 31995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3200763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 32014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 32024da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 32034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 32045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 32055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 32065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 32072149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_DATA: 32082149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_ID_DATA: { 32092149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 32102149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov int segmentCount = pathSegments.size(); 32112149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount < 4) { 32122149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 32132149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov "Missing a lookup key", uri)); 32142149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 32152149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String lookupKey = pathSegments.get(2); 32162149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount == 5) { 32172149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 32182149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 32192149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(lookupQb, uri, projection, false); 3220a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 3221a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 3222a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 3223a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey); 3224a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 32252149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov return c; 32262149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 32272149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 32282149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov // TODO see if the contact exists but has no data rows (rare) 32292149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 32302149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 32312149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 32322149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 32332149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 32342149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov qb.appendWhere(" AND " + Data.CONTACT_ID + "=?"); 32352149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov break; 32362149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 32372149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 3238f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 3239f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 324042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 3241763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 3242f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 32434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 32444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 32454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 3246f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 3247f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 3248f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 324942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 325042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 325142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 325242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return db.rawQuery( 325342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 325442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 325542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 325642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 325742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 325842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 3259ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3260916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 3261ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 3262916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 3263ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3264916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet(qb, uri, projection, filterParam); 3265385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov appendLocalDirectorySelectionIfNeeded(qb, directoryId); 3266ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3267ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3268ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3269ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3270ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 32714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3272ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3273d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 32744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 32754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3276e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 32775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 32784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 32794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 32804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3281763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3282ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 32835e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 32845e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 32855e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 3286dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov starredProjection = 3287dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov appendProjectionArg(projection, TIMES_CONTACTED_SORT_COLUMN); 3288dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov frequentProjection = 3289dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov appendProjectionArg(projection, TIMES_CONTACTED_SORT_COLUMN); 32905e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 32915e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 32924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 32934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 32944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3295d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 32965e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 32975e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 32984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3299d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3300d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3301d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3302763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 33034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 33044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3305d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 33065e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 33075e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 3308d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3309d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 33104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3311d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3312d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3313d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3314d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 33154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 33164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3317d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3318d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3319d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3320d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3321d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3322d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3323ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3324763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3325b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 332671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 33274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3328b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3329b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3330b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3331b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3332a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_DATA: { 33334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 333482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 33354da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 33364da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 33376bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 33386bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 333900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3340a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 33413653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 334282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 33434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 33444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 33453653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 33463653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 33473653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 33483653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 3349a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_ENTITIES: { 3350a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 3351a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 3352a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 3353a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 3354a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 3355a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3356a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3357a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ENTITIES: 3358a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ID_ENTITIES: { 3359a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 3360a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov int segmentCount = pathSegments.size(); 3361a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount < 4) { 3362a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3363a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov "Missing a lookup key", uri)); 3364a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3365a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lookupKey = pathSegments.get(2); 3366a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount == 5) { 3367a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 3368a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3369a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(lookupQb, uri, projection); 3370a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 3371a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3372a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 3373a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 3374a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.CONTACT_ID, contactId, 3375a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.LOOKUP_KEY, lookupKey); 3376a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 3377a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 3378a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3379a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3380a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3381a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 3382a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 3383a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 3384a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?"); 3385a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 3386a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3387a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 33884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 338982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 339089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 33912815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 33922815f58f72f109790585931f601a63ddc02536a5Evan Millar } 33932815f58f72f109790585931f601a63ddc02536a5Evan Millar 339448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 339582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 33964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 339748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 33984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 339948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 340048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 340148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3402ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 340382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 340489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3405ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 34064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 34074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3408a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 34095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 341045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 34115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 34125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 34135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 34145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 34157318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 34165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 341745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 34185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 34195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3420892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filterParam); 3421892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (!TextUtils.isEmpty(number)) { 34225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 34235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 34245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 34255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 3426892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov " IN (SELECT DISTINCT " + PhoneLookupColumns.DATA_ID 3427892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 3428892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 3429892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append(number); 3430892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append("%')"); 343145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 343245d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 343345d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 343445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 343545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 343645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 343745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 34385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 34395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 3440a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 3441ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 34425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3443a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3444a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3445a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 3446ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3447ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3448ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 34494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 345082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 345189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 34524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 34534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 34544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 345548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 345682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 34574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 34584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 34594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 346048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 346148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 346248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 34635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 346482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 346589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 34664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 346708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 346808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String address = mDbHelper.extractAddressFromEmailAddress(email); 346908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 347008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 34714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3472ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3473ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3474ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 34755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 347682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 347707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 347807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 347907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 348007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 348107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 348207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 348307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 34845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 348507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 348607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 348707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 348807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 348907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 349007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 349107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 349207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 349307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 34942a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "="); 34952a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForEmail()); 34962a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(" AND " + Data.DATA1 + " LIKE "); 349707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 349820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 349920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 350020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 350107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 350207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov /* 350307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * Using a UNION instead of an "OR" to make SQLite use the right 350407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * indexes. We need it to use the (mimetype,data1) index for the 350507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * email lookup (see above), but not for the name lookup. 350607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * SQLite is not smart enough to use the index on one side of an OR 350707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * but not on the other. Using two separate nested queries 350807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * and a UNION between them does the job. 350907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov */ 351007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 351107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " UNION SELECT " + Data._ID + 351207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 35132a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "="); 35142a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForEmail()); 35152a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(" AND " + Data.RAW_CONTACT_ID + " IN "); 35167318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 351720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 35185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 3520a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 35215e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 3523a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3524c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov sortOrder = EMAIL_FILTER_SORT_ORDER; 3525a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 35265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 35275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3529ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 353082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 353189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 353289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3533ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3534ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3535ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 353648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 353782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 35384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 353948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 354048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 35414da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 354248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 354348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 354448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 35455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 3546763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 35474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 35484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 35515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 3552763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 35534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 35544da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 35554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 35564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 35595ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 356082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 35614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 35624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 3563e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3564e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3565e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 3566e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 356782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3568e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3569e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3570e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 35714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 357282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 35734da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 35744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 3575a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3576a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3577a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3578a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 35794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3580a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 3581a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 3582a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 3583892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sortOrder = " length(lookup.normalized_number) DESC"; 3584a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3585a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3586e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 3587e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov String numberE164 = PhoneNumberUtils.formatNumberToE164(number, 3588e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov mDbHelper.getCurrentCountryIso()); 3589892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String normalizedNumber = 3590892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.normalizeNumber(number); 3591892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, normalizedNumber, numberE164); 3592e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 3593e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 3594e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 3595e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 3596a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3597a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3598a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3599ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 3600b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3601ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 360289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3603ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3604ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3605ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3606ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3607b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3608ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 36094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 36104da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 3611ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3612ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3613ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3614ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 3615b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 3616ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 361789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 361889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 3619ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3620ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3621ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3622b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 36230c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 3624b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 3625b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3626b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3627b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 362831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 3629d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 36302d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 36312d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 36322d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 36332d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 363431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 3635d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 3636d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 363731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 363831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 363931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 364031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 36415b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ArrayList<AggregationSuggestionParameter> parameters = null; 36425b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov List<String> query = uri.getQueryParameters("query"); 36435b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov if (query != null && !query.isEmpty()) { 36445b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters = new ArrayList<AggregationSuggestionParameter>(query.size()); 36455b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov for (String parameter : query) { 36465b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov int offset = parameter.indexOf(':'); 36475b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters.add(offset == -1 36485b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ? new AggregationSuggestionParameter( 364976dfa406e2cde19c824983c37fc92c1c5bf63eecDaniel Lehmann AggregationSuggestions.PARAMETER_MATCH_NAME, 36505b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter) 36515b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov : new AggregationSuggestionParameter( 36525b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(0, offset), 36535b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(offset + 1))); 36545b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 36555b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 36565b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 3657763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 36587581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 36597581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 36605b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov maxSuggestions, filter, parameters); 366131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 366231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3663eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3664eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 3665eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 366689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3667e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3668e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 3669e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 3670b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 3671e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 367282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3673b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3674e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3675e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 367682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3677b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3678e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3679e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3680e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3681eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3682eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3683eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 368482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 36850a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 36865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 36875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 36885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 368982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 36900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 36914da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 36924da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 36935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 36945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 36955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 3696c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 3697a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 3698c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3699c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3700c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 37012d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 37022d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill return mGlobalSearchSupport.handleSearchShortcutRefresh(db, lookupKey, projection); 3703c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3704c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 37051b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 3706b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37071b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 37081b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37091b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37101b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 3711b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37121b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 37131b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 37141b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37151b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37161b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 3717b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37181b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 37191b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 37201b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 37221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 3723b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 37241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 372571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 37261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 37271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 37281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 372946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 3730a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 373146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 373246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 373346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 373446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 373546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 3736a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 37374da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 37384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 373946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 374046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 374146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 374209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 374309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 374409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 374509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 3746d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES : { 3747d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 3748d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 3749d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 3750d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3751d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3752d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID : { 3753385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov long id = ContentUris.parseId(uri); 3754d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 3755d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 3756385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(id)); 3757d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Directory._ID + "=?"); 3758d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 3759d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3760d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 37617a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov case COMPLETE_NAME: { 37627a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return completeName(uri, projection); 37637a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 37647a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 37654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 3766f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 3767c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 37684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 37707f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov qb.setStrictProjectionMap(true); 37717f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 3772ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 3773ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 3774ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 3775ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov cursor = bundleLetterCountExtras(cursor, db, qb, selection, selectionArgs, sortOrder); 3776ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3777ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 37785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 37795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 37805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 37815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 37825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 3783038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 3784038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 3785038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 3786038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 37875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 37885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 37894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 37904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 37914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 37934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 379509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 379609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 379709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 379809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 379909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 380009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 380109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 380209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 380309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 380409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 380509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 380609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 380709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 380809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 380909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 381009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 3811a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 3812a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Runs the query with the supplied contact ID and lookup ID. If the query succeeds, 3813a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * it returns the resulting cursor, otherwise it returns null and the calling 3814a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * method needs to resolve the lookup key and rerun the query. 3815a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 3816a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private Cursor queryWithContactIdAndLookupKey(SQLiteQueryBuilder lookupQb, 3817a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteDatabase db, Uri uri, 3818a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection, String selection, String[] selectionArgs, 3819a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String sortOrder, String groupBy, String limit, 3820a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn, long contactId, String lookupKeyColumn, String lookupKey) { 3821a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] args; 3822a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (selectionArgs == null) { 3823a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[2]; 3824a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 3825a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[selectionArgs.length + 2]; 3826a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 3827a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3828a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[0] = String.valueOf(contactId); 3829a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[1] = Uri.encode(lookupKey); 3830a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(contactIdColumn + "=? AND " + lookupKeyColumn + "=?"); 3831a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 3832a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov groupBy, limit); 3833a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c.getCount() != 0) { 3834a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 3835a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3836a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3837a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov c.close(); 3838a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return null; 3839a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 384009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 3841bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 3842bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 3843bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 3844bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 3845ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3846bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 3847bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 3848ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 3849ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3850bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 3851bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 3852bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 3853bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 3854de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 3855ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3856ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3857ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 3858ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 3859ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 3860ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 3861ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 3862ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder) { 3863ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 3864ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3865ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 3866ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 3867ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 3868ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 3869ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 3870ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 3871ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 3872ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 3873ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 3874ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 3875ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 3876ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3877ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 3878ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 3879ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3880ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3881bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 3882ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 3883bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 3884bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "SUBSTR(" + sortKey + ",1,1) AS " + AddressBookIndexQuery.LETTER); 3885bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 3886bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 3887bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 3888bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 3889bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 3890bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 3891bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 3892bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 3893ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 3894bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "GET_PHONEBOOK_INDEX(SUBSTR(" + sortKey + ",1,1),'" + locale + "')" 3895bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 3896ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 3897ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov "COUNT(" + Contacts._ID + ") AS " + AddressBookIndexQuery.COUNT); 3898ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 3899ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3900f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 3901ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 3902ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 3903ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3904ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 3905f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 3906ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 3907ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 3908bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 3909bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 3910bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 3911bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 3912bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 3913bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 3914ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 3915f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 3916bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 3917bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 3918bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 3919bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 3920bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 3921bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 3922bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 3923bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 3924bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 3925bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 3926bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 3927bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 3928bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 3929bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 3930bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 3931bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 3932bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 3933bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 3934bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 3935ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3936ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3937ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov final Bundle bundle = new Bundle(); 3938ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 3939f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 3940ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return new CursorWrapper(cursor) { 3941ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3942ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov @Override 3943ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov public Bundle getExtras() { 3944ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return bundle; 3945ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3946ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 3947ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 3948f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 3949ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3950ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3951ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 39522d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 395392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 395492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 395592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 395692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 39572d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 39582d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 39595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 39605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 39615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 396292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 396392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 396492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 396592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 396692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 396792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 396892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 396992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 397092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 397192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 397292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 397392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 397492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 397592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 397692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 397792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 397892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 397992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 398092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 39815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 39825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 39855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 39885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 39895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 39915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 39925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 39935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 39945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 39955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 39965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 39985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 39995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 40005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 40015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 40045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 40055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 40065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 40075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 40085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 400992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 40105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 40115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 40125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 40155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 40165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 40185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 40195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 40205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 40215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 40225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 40235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 40245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 40255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 40265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 40275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 402892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 402992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 40305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 40315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 40325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 40335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 40375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 40385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 40415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 404392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 404492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 40455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 40475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 40485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 40495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 405092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 40515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 40525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 40545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 40555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 405692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 40575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 405992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 406092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 406192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 406292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 40635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 40645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 406592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 406692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 406792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 40685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 407092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 407192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 40725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 407392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 407492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 407592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 407692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 407792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountType = c.getString(LookupByRawContactIdQuery.ACCOUNT_TYPE); 407892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 407992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 408092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 408192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 408292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 408392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 408492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 408592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 408692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 408792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 408892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 408992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 409092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 409192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 409292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 409392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 40945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 409692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 409792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 409892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 409992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 410092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 410192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 410292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 410392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 410492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 410592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 410692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 410792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 410892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 410992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 411092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_TYPE = 1; 411192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 411292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 411392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 411492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 411592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 411692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 41175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 41185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 41195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 41205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 412192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 412292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 41235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 41245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 41255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 41285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 41295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 41305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 41325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 41335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 41345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 41355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 41365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 41375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 41385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 41395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 41405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 41415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 414292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 414392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 414492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 41455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 41465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 41475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 41485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 41525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 41535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 41565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 415892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 415992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 416092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 416192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 416292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 416392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 416492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 416592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 416692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 416792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 416892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 4169ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 4170ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(db, rawContactId); 4171ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 4172ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 41735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 41745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 41755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 41765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 41775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 41785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 41805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 41815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 41835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 41845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 41865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 41875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 41885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 41895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 41905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 41915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 41925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 41935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 41945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 41955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 41975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 41985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 42025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 42035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 42045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 42055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4208763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 4209763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 421082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4211916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 4212916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 4213916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 4214916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4215916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4216916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 4217916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 4218916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 4219916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 4220916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 4221916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String[] projection, String filter) { 4222916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4223916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4224916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 4225916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4226916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(" JOIN (SELECT " + 4227916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov RawContacts.CONTACT_ID + " AS snippet_contact_id"); 4228916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4229916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA_ID)) { 4230916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", " + DataColumns.CONCRETE_ID + " AS " 4231916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov + SearchSnippetColumns.SNIPPET_DATA_ID); 4232916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4233916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 42349c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA1)) { 42359c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA1 + " AS " + SearchSnippetColumns.SNIPPET_DATA1); 4236916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4237916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 42389c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA2)) { 42399c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA2 + " AS " + SearchSnippetColumns.SNIPPET_DATA2); 4240916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4241916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 42429c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA3)) { 42439c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA3 + " AS " + SearchSnippetColumns.SNIPPET_DATA3); 42449c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 42459c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov 42469c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA4)) { 42479c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA4 + " AS " + SearchSnippetColumns.SNIPPET_DATA4); 4248916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4249916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4250916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_MIMETYPE)) { 4251916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", (" + 4252916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov "SELECT " + MimetypesColumns.MIMETYPE + 4253916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " FROM " + Tables.MIMETYPES + 4254916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + MimetypesColumns._ID + "=" + DataColumns.MIMETYPE_ID + 4255916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov ") AS " + SearchSnippetColumns.SNIPPET_MIMETYPE); 4256916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4257916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4258c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS + " WHERE "); 4259c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov 4260c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov if (!TextUtils.isEmpty(filter)) { 42616b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov String normalizedFilter = NameNormalizer.normalize(filter); 42626b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov if (!TextUtils.isEmpty(normalizedFilter)) { 42636b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov sb.append(DataColumns.CONCRETE_ID + " IN ("); 42646b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov 42656b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov // Construct a query that gives us exactly one data _id per matching contact. 42666b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov // MIN stands in for ANY in this context. 42676b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov sb.append( 42686b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov "SELECT MIN(" + Tables.NAME_LOOKUP + "." + NameLookupColumns.DATA_ID + ")" + 42696b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 42706b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 42716b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov " ON (" + RawContactsColumns.CONCRETE_ID 42726b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov + "=" + Tables.NAME_LOOKUP + "." 42736b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 42746b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + " GLOB '"); 42756b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov sb.append(normalizedFilter); 42766b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 42776b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + ")" + 42786b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov " GROUP BY " + RawContactsColumns.CONCRETE_CONTACT_ID + 42796b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov ")"); 42806b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov } else { 42816b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov sb.append("0"); // Empty filter - return an empty set 42826b759a2b977a29c3c4abe1eb6d2ba242f937a923Dmitri Plotnikov } 4283c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov } else { 4284c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append("0"); // Empty filter - return an empty set 4285c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov } 4286c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov 4287c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append(") ON (" + Contacts._ID + "=snippet_contact_id)"); 4288916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4289916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 4290916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 4291916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4292916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4293916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void appendContactsTables(StringBuilder sb, Uri uri, String[] projection) { 4294763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4295f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4296763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4297763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4298d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4299763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4300763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 4301a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 4302a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 430382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4304ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 4305763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 4306763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 4307763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4308f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4309763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4310763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4311d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4312763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4313763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 4314763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 4315763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 4316763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 4317763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4318763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4319a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForRawEntities(SQLiteQueryBuilder qb, Uri uri) { 4320a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(mDbHelper.getRawEntitiesView(shouldExcludeRestrictedData(uri))); 4321a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sRawEntityProjectionMap); 432246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 432346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 432446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 432582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 432682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 432782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4328a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(mDbHelper.getDataView(shouldExcludeRestrictedData(uri))); 432982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 433082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 4331a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, RawContacts.CONTACT_ID); 4332a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 4333a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 4334a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 43353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 433682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 4337f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 4338f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov boolean useDistinct = distinct 4339f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov || !mDbHelper.isInProjection(projection, DISTINCT_DATA_PROHIBITING_COLUMNS); 4340f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setDistinct(useDistinct); 4341f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setProjectionMap(useDistinct ? sDistinctDataProjectionMap : sDataProjectionMap); 434282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 4343ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 4344ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 43450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 43460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 43470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4348b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 43490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 4350a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 4351a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 43520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4353a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 4354a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 4355a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4356a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4357a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForEntities(SQLiteQueryBuilder qb, Uri uri, 4358a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection) { 4359a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4360a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(mDbHelper.getEntitiesView(shouldExcludeRestrictedData(uri))); 4361a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" data"); 4362a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4363a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts.Entity.CONTACT_ID); 4364a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 4365a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, Contacts.Entity.DATA_ID); 4366a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, Contacts.Entity.DATA_ID); 4367a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4368a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 4369a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sEntityProjectionMap); 4370a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4371a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4372a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4373a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactStatusUpdateJoin(StringBuilder sb, String[] projection, 4374a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lastStatusUpdateIdColumn) { 4375a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 4376a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS, 4377a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 4378a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 4379a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 4380a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 4381a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 4382a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 4383a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + lastStatusUpdateIdColumn + "=" 4384a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 43850a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 4386a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 43870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4388a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataStatusUpdateJoin(StringBuilder sb, String[] projection, 4389a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 4390b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 43910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 43920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 43930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 43940a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 43950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 43960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 4397a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 4398a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + dataIdColumn + ")"); 43990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 4400a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4401a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4402a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactPresenceJoin(StringBuilder sb, String[] projection, 4403a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn) { 4404a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 4405a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_PRESENCE, Contacts.CONTACT_CHAT_CAPABILITY)) { 4406a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 4407a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + contactIdColumn + " = " 4408a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + ")"); 4409a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4410a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4411a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4412a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataPresenceJoin(StringBuilder sb, String[] projection, 4413a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 4414a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.PRESENCE, Data.CHAT_CAPABILITY)) { 4415a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 4416a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdates.DATA_ID + "=" + dataIdColumn + ")"); 4417a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4418a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4419a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4420385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov private void appendLocalDirectorySelectionIfNeeded(SQLiteQueryBuilder qb, long directoryId) { 4421385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directoryId == Directory.DEFAULT) { 4422385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " IN " + Tables.DEFAULT_DIRECTORY); 4423385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directoryId == Directory.LOCAL_INVISIBLE){ 4424385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " NOT IN " + Tables.DEFAULT_DIRECTORY); 4425385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } 4426385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } 4427385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov 4428a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private boolean shouldExcludeRestrictedData(Uri uri) { 4429a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov // Note: currently, "export only" equals to "restricted", but may not in the future. 4430a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov boolean excludeRestrictedData = readBooleanQueryParameter(uri, 4431a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.FOR_EXPORT_ONLY, false); 4432a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (excludeRestrictedData) { 4433a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return true; 4434a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4435a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4436a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4437a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4438a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (requestingPackage != null) { 4439a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4440a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4441a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4442a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return false; 44430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 44440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 44454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 4446f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 4447f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 4448e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4449e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 4450e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 4451e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 4452fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4453fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 4454e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4455e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4456e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 4457e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 4458e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 4459e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 44604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 44614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 44624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 44634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 44644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 44654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 44664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 44674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 44684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4469e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 4470f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 4471f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 4472e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4473e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 4474e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 4475e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 4476fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4477fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 4478e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4479e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4480e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 4481e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 4482e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 4483e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 4484e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 4485e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4486e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 4487e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 4488e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 4489e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 4490e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 4491e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 4492e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4493e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 4494e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 4495e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 4496e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4497e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4498e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 44997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 4500c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 4501c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 4502c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 4503c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 4504c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 4505f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 45062e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limitParam = getQueryParameter(uri, ContactsContract.LIMIT_PARAM_KEY); 4507c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 4508c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4509c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4510c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 4511c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 4512c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 4513c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 4514c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4515c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4516c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4517c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 4518c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 4519c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4520c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4521c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4522c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4523c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 452400ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 4525d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 452670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 452770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 4528fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0"; 452970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 453070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 453170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 453270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 4533d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 453470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 453567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 45365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 45375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 4538619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4539619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4540619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4541b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 4542f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 4543b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 4544b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 4545a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 4546f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return openPhotoAssetFile(uri, mode, 4547e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=" + Contacts.PHOTO_ID + " AND " + RawContacts.CONTACT_ID + "=?", 4548e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 4549e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 4550b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4551e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 4552f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return openPhotoAssetFile(uri, mode, 4553e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=? AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'", 45544da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 4555d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4556d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4557f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 455849d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 455942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 456049d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(lookupContactIdByLookupKey(db, lookupKey)); 456142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + "=?"; 456242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 456342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 456442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 456542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 456642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 456742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann outputRawContactsAsVCard(localStream, selection, mSelectionArgs1); 4568f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 456942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 457042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 457142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 457249d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 457342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 457442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 457542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 457642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 4577d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 4578d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 457942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 458042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 4581d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 458242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 4583d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 458442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 458549d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov inBuilder.append(lookupContactIdByLookupKey(db, lookupKey)); 458642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 458742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 458842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 458942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 4590d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4591d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 4592d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 4593d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 4594d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 4595d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann outputRawContactsAsVCard(localStream, selection, null); 4596f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 4597d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4598b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4599b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 4600fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("File does not exist", 4601fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov uri)); 4602b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4603b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4604b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4605f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor openPhotoAssetFile(Uri uri, String mode, String selection, 4606e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String[] selectionArgs) 4607e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 4608e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 4609e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("Mode " + mode 4610e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 4611e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 4612e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 4613e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 4614e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 4615e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 4616e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 461708ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood try { 4618f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 4619f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert DatabaseUtils.blobFileDescriptorForQuery(db, sql, selectionArgs)); 462008ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } catch (SQLiteDoneException e) { 462108ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood // this will happen if the DB query returns no rows (i.e. contact does not exist) 462208ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood throw new FileNotFoundException(uri.toString()); 462308ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } 4624e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 4625e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 4626d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 4627d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4628d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4629f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert * Returns an {@link AssetFileDescriptor} backed by the 4630d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 4631d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4632f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 4633d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 4634d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 4635d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4636d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 4637d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4638f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 4639f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert ParcelFileDescriptor.fromData(byteData, CONTACT_MEMORY_FILE_NAME), 4640f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert byteData.length); 4641d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 4642ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert Log.w(TAG, "Problem writing stream into an ParcelFileDescriptor: " + e.toString()); 4643ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return null; 4644d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4645d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4646d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4647f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd) { 4648f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor(fd, AssetFileDescriptor.UNKNOWN_LENGTH); 4649f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 4650f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 4651f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd, long length) { 4652f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return fd != null ? new AssetFileDescriptor(fd, 0, length) : null; 4653f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 4654f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 4655d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4656d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 4657d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 4658d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 4659d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4660d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 4661d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 4662d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 46637a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 46647a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa new VCardComposer(context, VCardConfig.VCARD_TYPE_DEFAULT, false); 4665d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 4666d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4667f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 46687a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa if (!composer.init(selection, selectionArgs)) { 46697a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 4670d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 46717a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa } 4672d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4673d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 4674d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 4675d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 4676d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4677d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4678d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 4679d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4680b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 46814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 46824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4683a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 46844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4685b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4686be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 46872d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 4688b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4689b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4690b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4691f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 469242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 4693f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 4694f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov case CONTACTS_ID_PHOTO: 4695f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov return "image/png"; 4696b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4697be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4698b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4699b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4700f481f22a9323fe338672f99b88b26c5f0725cd42David Brown case DATA: 4701f481f22a9323fe338672f99b88b26c5f0725cd42David Brown return Data.CONTENT_TYPE; 4702508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4703b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 470448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 470548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 470648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 470748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 47089005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 47099005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 471048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 471148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 471248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 471348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 471448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 471548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 471648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 471748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4718b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4719b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4720b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4721b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4722b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4723b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4724b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4725b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4726c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4727c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4728c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4729c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 4730d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES: 4731d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_TYPE; 4732d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID: 4733d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_ITEM_TYPE; 473461efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 473561efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 47364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 47387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 473909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public String[] getDefaultProjection(Uri uri) { 474009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov final int match = sUriMatcher.match(uri); 474109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov switch (match) { 474209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS: 474309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP: 474409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_ID: 474509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP_ID: 474609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 474709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsProjectionMap.getColumnNames(); 474809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 47498727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov case CONTACTS_ID_ENTITIES: 47508727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov return sEntityProjectionMap.getColumnNames(); 47518727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov 475209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_VCARD: 475309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_MULTI_VCARD: 475409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsVCardProjectionMap.getColumnNames(); 475509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 475609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS: 475709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS_ID: 475809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sRawContactsProjectionMap.getColumnNames(); 475909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 476009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DATA_ID: 476109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES: 476209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES_ID: 476309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS: 476409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS_ID: 476509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS: 476609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS_ID: 476709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDataProjectionMap.getColumnNames(); 476809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 476909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONE_LOOKUP: 477009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sPhoneLookupProjectionMap.getColumnNames(); 477109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 477209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 477309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 477409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sAggregationExceptionsProjectionMap.getColumnNames(); 477509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 477609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case SETTINGS: 477709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sSettingsProjectionMap.getColumnNames(); 477809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 477909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES: 478009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES_ID: 478109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDirectoryProjectionMap.getColumnNames(); 478209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 478309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov default: 478409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return null; 478509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 478609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 478709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 4788f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 4789f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4790f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 4791f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 4792f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4793f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4794f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4795f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 4796f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 479778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.insertNameLookup(rawContactId, dataId, lookupType, name); 4798f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4799f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4800f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4801f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4802d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 4803f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4804f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4805f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 48062d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 4807d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4808d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 4809d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4810d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 4811d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 4812d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 4813d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 4814e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 4815916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 4816916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 4817e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 4818e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 48195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 4820c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 48217318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam); 4822c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 4823c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4824c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 48257318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam) { 48267318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), true); 48275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 48285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 48295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 48307318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov boolean allowEmailMatch) { 483123061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov if (TextUtils.isEmpty(normalizedName)) { 483223061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov // Effectively an empty IN clause - SQL syntax does not allow an actual empty list here 483323061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append("(0)"); 483423061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov } else { 483523061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append("(" + 483623061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov "SELECT " + NameLookupColumns.RAW_CONTACT_ID + 483723061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 483823061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 483923061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov " GLOB '"); 484023061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov // Should not use a "?" argument placeholder here, because 484123061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov // that would prevent the SQL optimizer from using the index on NORMALIZED_NAME. 484223061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append(normalizedName); 484323061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 484423061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 484523061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov + NameLookupType.NICKNAME + "," 484623061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov + NameLookupType.NAME_SHORTHAND + "," 484723061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov + NameLookupType.ORGANIZATION + "," 484823061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov + NameLookupType.NAME_CONSONANTS); 484923061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov if (allowEmailMatch) { 485023061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 485123061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov } 485223061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append("))"); 485323061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov } 4854ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4855ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 48564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 48577a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * Takes components of a name from the query parameters and returns a cursor with those 48587a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * components as well as all missing components. There is no database activity involved 48597a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * in this so the call can be made on the UI thread. 48607a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov */ 48617a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private Cursor completeName(Uri uri, String[] projection) { 48627a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (projection == null) { 48637a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov projection = sDataProjectionMap.getColumnNames(); 48647a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 48657a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 48667a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ContentValues values = new ContentValues(); 4867f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov DataRowHandlerForStructuredName handler = (DataRowHandlerForStructuredName) 4868f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov getDataRowHandler(StructuredName.CONTENT_ITEM_TYPE); 48697a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 48707a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov copyQueryParamsToContentValues(values, uri, 48717a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.DISPLAY_NAME, 48727a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PREFIX, 48737a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.GIVEN_NAME, 48747a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.MIDDLE_NAME, 48757a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.FAMILY_NAME, 48767a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.SUFFIX, 48777a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_NAME, 48787a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_FAMILY_NAME, 48797a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_MIDDLE_NAME, 48807a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_GIVEN_NAME 48817a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ); 48827a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 48837a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov handler.fixStructuredNameComponents(values, values); 48847a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 48857a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 48867a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov Object[] row = new Object[projection.length]; 48877a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (int i = 0; i < projection.length; i++) { 48887a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov row[i] = values.get(projection[i]); 48897a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 48907a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.addRow(row); 48917a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return cursor; 48927a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 48937a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 48947a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private void copyQueryParamsToContentValues(ContentValues values, Uri uri, String... columns) { 48957a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (String column : columns) { 48967a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String param = uri.getQueryParameter(column); 48977a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (param != null) { 48987a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov values.put(column, param); 48997a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 49007a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 49017a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 49027a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 49037a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 49047a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov /** 49054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 49064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 49074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 4908b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 4909b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 4910b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 4911b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 4912b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 49134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 49144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 4915b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 4916b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4917b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4918caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 49195e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 49205e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 49215e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 49225e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 49235e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 49245e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 49255e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 49265e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 49275e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 49285e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 49295e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 4930caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 4931caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 4932caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 4933df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 4934df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 4935caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 4936caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 4937caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 4938caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 49396f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 4940caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 49416f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 4942caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 4943f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 494473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 494573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov * Returns true if the specified account type is writable. 494673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 494773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov protected boolean isWritableAccount(String accountType) { 4948bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov if (accountType == null) { 4949bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 4950bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 4951bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 495273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov Boolean writable = mAccountWritability.get(accountType); 495373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 495473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 495573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 495673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 4957627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 4958627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4959627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 4960627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 496173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov accountType.equals(sync.accountType)) { 496273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 496373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 4964627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4965627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4966627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 4967627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 4968627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 496973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 497073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 497173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 497273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 497373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 497473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.put(accountType, writable); 497573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 4976627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4977b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 4978d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4979f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 4980f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 4981f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4982f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 4983f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 4984f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 4985f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 4986f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 4987f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4988f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 4989f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 4990f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 4991f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 4992f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4993f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 4994f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4995f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 4996f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 4997f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 4998f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 4999f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 5000f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 5001f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 5002f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 5003f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 5004f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5005f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5006f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 5007f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 5008f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 5009f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 5010f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5011f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5012f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5013f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5014f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5015f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 5016f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 5017f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5018f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 5019f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 5020f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 5021f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 5022f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5023f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5024f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5025f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5026f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 5027f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5028f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 5029f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5030f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5031f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5032f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 5033f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 5034f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 5035f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5036f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5037f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5038f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 5039f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 5040f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 5041f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 5042f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 5043f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5044f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5045f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 5046f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 50475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 50480dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov protected boolean isAggregationUpgradeNeeded() { 50490dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 50500dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return false; 50510dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 50520dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 50530dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_AGGREGATION_ALGORITHM, "1")); 50540dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return version < PROPERTY_AGGREGATION_ALGORITHM_VERSION; 50550dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 50560dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 5057bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void upgradeAggregationAlgorithmInBackground() { 50580dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // This upgrade will affect very few contacts, so it can be performed on the 50590dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // main thread during the initial boot after an OTA 50600dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 50610dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Upgrading aggregation algorithm"); 50620dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int count = 0; 50630dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 50640dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 506549d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 50660dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDb.beginTransaction(); 50670dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Cursor cursor = mDb.query(true, 50680dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Tables.RAW_CONTACTS + " r1 JOIN " + Tables.RAW_CONTACTS + " r2", 50690dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov new String[]{"r1." + RawContacts._ID}, 50700dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov "r1." + RawContacts._ID + "!=r2." + RawContacts._ID + 50710dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.CONTACT_ID + "=r2." + RawContacts.CONTACT_ID + 50720dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_NAME + "=r2." + RawContacts.ACCOUNT_NAME + 50730dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_TYPE + "=r2." + RawContacts.ACCOUNT_TYPE, 50740dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov null, null, null, null, null); 50750dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 50760dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov while (cursor.moveToNext()) { 50770dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long rawContactId = cursor.getLong(0); 50780dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, 50790dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 50800dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov count++; 50810dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 50820dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 50830dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov cursor.close(); 50840dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 50850dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.aggregateInTransaction(mDb); 50860dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDb.setTransactionSuccessful(); 50870dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDbHelper.setProperty(PROPERTY_AGGREGATION_ALGORITHM, 50880dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov String.valueOf(PROPERTY_AGGREGATION_ALGORITHM_VERSION)); 50890dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 50900dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDb.endTransaction(); 50910dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 50920dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Aggregation algorithm upgraded for " + count 50930dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov + " contacts, in " + (end - start) + "ms"); 50940dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 50950dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 50964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 5097