ContactsProvider2.java revision 03197a00e17386aa9b1971bde3cda034bc17e0c3
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 19d9ec58265ae59a549880ef63cdfb5d0d977cdabaDmitri Plotnikovimport com.android.common.content.SQLiteContentProvider; 2053214b3ed12b0ff9cb589b6559311f2ac142f2e3Bjorn Bringertimport com.android.common.content.SyncStateContentProviderHelper; 215b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport com.android.providers.contacts.ContactAggregator.AggregationSuggestionParameter; 2297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 2397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 2497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 2597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 2697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 2797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 2897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 2997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 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; 3603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns; 3797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 3897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 3997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 4097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.vcard.VCardComposer; 4197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.vcard.VCardConfig; 4297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Lists; 4397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Maps; 4497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Sets; 4597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 46b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 47caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 485b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 49bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.Notification; 50bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.NotificationManager; 51bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.PendingIntent; 52c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 53568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 54568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 556ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 5635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 59627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.IContentService; 60bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.content.Intent; 61568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 63627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 6467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 65f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringertimport android.content.res.AssetFileDescriptor; 66e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikovimport android.database.CrossProcessCursor; 674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 68e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikovimport android.database.CursorWindow; 69ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.CursorWrapper; 70ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 7109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor; 7209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor.RowBuilder; 734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 7408ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwoodimport android.database.sqlite.SQLiteDoneException; 754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 77d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.net.Uri.Builder; 78bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Binder; 796ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 80bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Handler; 81bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.HandlerThread; 82bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Message; 83ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringertimport android.os.ParcelFileDescriptor; 84bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Process; 85b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 8615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikovimport android.os.StrictMode; 870dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikovimport android.os.SystemClock; 880e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 893d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 90508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 913de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 92b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 9397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 9497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 9597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 9697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 976d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Note; 9897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 9997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 10097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 10197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 10297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 103ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 1043de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 1055b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions; 1063de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 107d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory; 1083de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 109bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.provider.ContactsContract.Intents; 1103de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 11109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 1123de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 113916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 1143de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 11582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 11697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.LiveFolders; 11797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.OpenableColumns; 11897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.SyncStateContract; 119a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 1209a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikovimport android.telephony.TelephonyManager; 121a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 122c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 124d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 125b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 126d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 127d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 12842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.text.SimpleDateFormat; 1297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 13142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.util.Date; 132b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1330e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 135622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 136b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1370e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 138ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1445b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 145caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 146bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 147bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 148bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 15015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_INITIALIZE = 0; 15115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_OPEN_WRITE_ACCESS = 1; 15215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS = 2; 15315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_ACCOUNTS = 3; 15415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_LOCALE = 4; 15515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM = 5; 15605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_SEARCH_INDEX = 6; 15705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_PROVIDER_STATUS = 7; 15805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_DIRECTORIES = 8; 15905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_CHANGE_LOCALE = 9; 160619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1643d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 165b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov * Property key for the legacy contact import version. The need for a version 1663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1673d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 169b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final String PROPERTY_CONTACTS_IMPORTED = "contacts_imported_v1"; 170b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int PROPERTY_CONTACTS_IMPORT_VERSION = 1; 17151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final String PREF_LOCALE = "locale"; 1723d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1730dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final String PROPERTY_AGGREGATION_ALGORITHM = "aggregation_v2"; 1740dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final int PROPERTY_AGGREGATION_ALGORITHM_VERSION = 2; 1750dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 1760e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1770e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 178a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 180dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov private static final String TIMES_CONTACTED_SORT_COLUMN = "times_contacted_sort"; 1815e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 182d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 183dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov + TIMES_CONTACTED_SORT_COLUMN + " DESC, " 1849b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 185d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 186d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 187d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 188d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1896e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 1909b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 1919b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1929b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 1939b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 1946e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 1959b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 1969b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1979b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 1989b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 199de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 200de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 201d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 202d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 2035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 2045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 205a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_DATA = 1004; 2065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 2075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 2085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 2095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 210a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_PHOTO = 1009; 211f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 21242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann private static final int CONTACTS_AS_MULTI_VCARD = 1011; 2132149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov private static final int CONTACTS_LOOKUP_DATA = 1012; 2142149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ID_DATA = 1013; 215a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_ENTITIES = 1014; 216a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ENTITIES = 1015; 217a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ID_ENTITIES = 1016; 2184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 2205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 2215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 22246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 2234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2246bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2256bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 226ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 22748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 22848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 22948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 23048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 23148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 23248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 23348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 23448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 235a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2366bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 2376bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 238b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 239b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 240b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 24182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 24282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 2431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 24431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 24531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 246eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 247eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 248ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 249ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 250ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 251ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 25235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 253b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 25435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 255c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 256c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 257c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 26346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 26446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 26509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 26609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 267d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES = 17001; 268d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES_ID = 17002; 269d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 2707a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private static final int COMPLETE_NAME = 18000; 2717a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 272dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID = 273dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 274dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME 275dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 276dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE 277dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_TYPE 278dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + " != 0"; 279dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 280dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID = 281dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 282dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 283dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 284dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 285dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND " 286dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + Groups.AUTO_ADD + " != 0"; 287dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 288dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String[] PROJECTION_GROUP_ID 289dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana = new String[]{Tables.GROUPS + "." + Groups._ID}; 290dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 291dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_GROUPMEMBERSHIP_DATA = DataColumns.MIMETYPE_ID + "=? " 292dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.GROUP_ROW_ID + "=? " 293dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.RAW_CONTACT_ID + "=?"; 294dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 295dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_STARRED_FROM_RAW_CONTACTS = 296dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT " + RawContacts.STARRED 297dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?"; 298dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 299e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public class AddressBookCursor extends CursorWrapper implements CrossProcessCursor { 300e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private final CrossProcessCursor mCursor; 301e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private final Bundle mBundle; 302e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 303e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public AddressBookCursor(CrossProcessCursor cursor, String[] titles, int[] counts) { 304e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov super(cursor); 305e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov mCursor = cursor; 306e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov mBundle = new Bundle(); 307e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov mBundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 308e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov mBundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 309e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 310e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 311e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov @Override 312e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public Bundle getExtras() { 313e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov return mBundle; 314e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 315e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 316e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov @Override 317e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public void fillWindow(int pos, CursorWindow window) { 318e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov mCursor.fillWindow(pos, window); 319e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 320e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 321e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov @Override 322e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public CursorWindow getWindow() { 323e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov return mCursor.getWindow(); 324e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 325e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 326e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov @Override 327e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public boolean onMove(int oldPosition, int newPosition) { 328e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov return mCursor.onMove(oldPosition, newPosition); 329e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 330e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 331e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 332d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 333f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 334f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 335f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 33667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 33767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 3386cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 3393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 340f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 341ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 342ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 343d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 34467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 345d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 346ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3471f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 348f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov interface RawContactsQuery { 34919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 35019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 35119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 352ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 353ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 354ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 35519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 35619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 35719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 358ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 359ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 36019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 36119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 362c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 363caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 36471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 36571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 36671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 36771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 36871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 36971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 37071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 37171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 37271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 37371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 37471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 37571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 37671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 37771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 378a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 379a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 380a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 381a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 382a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 383a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 384a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 385a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 386a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 387a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 388a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 389a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 390c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Current contacts - those contacted within the last 3 days (in seconds) 391c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_CURRENT = 3 * 24 * 60 * 60; 392c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 393c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Recent contacts - those contacted within the last 30 days (in seconds) 394c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_RECENT = 30 * 24 * 60 * 60; 395c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 396c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final String TIME_SINCE_LAST_CONTACTED = 397c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov "(strftime('%s', 'now') - " + Contacts.LAST_TIME_CONTACTED + "/1000)"; 398c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 399c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov /* 400c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * Sorting order for email address suggestions: first starred, then the rest. 401c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * Within the starred/unstarred groups - three buckets: very recently contacted, then fairly 402c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * recently contacted, then the rest. Within each of the bucket - descending count 403c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * of times contacted. If all else fails, alphabetical. (Super)primary email 404c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * address is returned before other addresses for the same contact. 405c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov */ 406c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final String EMAIL_FILTER_SORT_ORDER = 407c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov "(CASE WHEN " + Contacts.STARRED + "=1 THEN 0 ELSE 1 END), " 408c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + "(CASE WHEN " + TIME_SINCE_LAST_CONTACTED + " < " + EMAIL_FILTER_CURRENT + " THEN 0 " 409c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + " WHEN " + TIME_SINCE_LAST_CONTACTED + " < " + EMAIL_FILTER_RECENT + " THEN 1 " 410c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + " ELSE 2 END)," 411c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + Contacts.TIMES_CONTACTED + " DESC, " 412c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + Contacts.DISPLAY_NAME + ", " 413c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + Data.CONTACT_ID + ", " 414c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov + Data.IS_SUPER_PRIMARY + " DESC"; 415c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 416916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 417916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 418916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 419916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 420916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NICKNAME + "," + 421916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_SHORTHAND + "," + 422f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.ORGANIZATION + "," + 423f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.NAME_CONSONANTS; 424916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 425f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov /** 426f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * If any of these columns are used in a Data projection, there is no point in 427f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * using the DISTINCT keyword, which can negatively affect performance. 428f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov */ 429f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov private static final String[] DISTINCT_DATA_PROHIBITING_COLUMNS = { 430f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data._ID, 431f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.RAW_CONTACT_ID, 432f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.NAME_RAW_CONTACT_ID, 433f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 434f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 435f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.DIRTY, 436f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.NAME_VERIFIED, 437f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SOURCE_ID, 438f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.VERSION, 439f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov }; 440916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 441f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsColumns = ProjectionMap.builder() 442f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CUSTOM_RINGTONE) 443f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME) 444f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_ALTERNATIVE) 445f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_SOURCE) 446f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.IN_VISIBLE_GROUP) 447f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LAST_TIME_CONTACTED) 448f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LOOKUP_KEY) 449f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME) 450f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME_STYLE) 451f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHOTO_ID) 4523d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_URI) 4533d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_THUMBNAIL_URI) 454f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SEND_TO_VOICEMAIL) 455f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_ALTERNATIVE) 456f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_PRIMARY) 457f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.STARRED) 458f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.TIMES_CONTACTED) 459cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 460f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 461f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 462f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsPresenceColumns = ProjectionMap.builder() 463f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 464f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE) 465f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 466f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 467f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 468f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 469f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 470f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 471f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 472f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 473f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 474f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 475f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 476f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 477f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 478f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 479f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSnippetColumns = ProjectionMap.builder() 48003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov .add(SearchSnippetColumns.SNIPPET) 481f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 482f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 483f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactColumns = ProjectionMap.builder() 484f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_NAME) 485f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_TYPE) 486f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DIRTY) 487f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.NAME_VERIFIED) 488f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SOURCE_ID) 489f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.VERSION) 490f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 491f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 492f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactSyncColumns = ProjectionMap.builder() 493f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC1) 494f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC2) 495f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC3) 496f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC4) 497f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 498f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 499f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataColumns = ProjectionMap.builder() 500f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA1) 501f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA2) 502f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA3) 503f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA4) 504f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA5) 505f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA6) 506f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA7) 507f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA8) 508f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA9) 509f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA10) 510f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA11) 511f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA12) 512f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA13) 513f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA14) 514f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA15) 515f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA_VERSION) 516f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_PRIMARY) 517f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_SUPER_PRIMARY) 518f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.MIMETYPE) 519f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RES_PACKAGE) 520f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC1) 521f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC2) 522f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC3) 523f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC4) 524f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(GroupMembership.GROUP_SOURCE_ID) 525f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 526f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 527f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactPresenceColumns = ProjectionMap.builder() 528f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 529f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.PRESENCE) 530f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 531f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.CHAT_CAPABILITY) 532f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 533f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 534f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 535f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 536f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 537f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 538f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 539f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 540f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 541f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 542f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 543f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 544f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataPresenceColumns = ProjectionMap.builder() 545f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.PRESENCE, Tables.PRESENCE + "." + StatusUpdates.PRESENCE) 546f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CHAT_CAPABILITY, Tables.PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 547f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS, StatusUpdatesColumns.CONCRETE_STATUS) 548f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_TIMESTAMP, StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 549f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_RES_PACKAGE, StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 550f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_LABEL, StatusUpdatesColumns.CONCRETE_STATUS_LABEL) 551f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_ICON, StatusUpdatesColumns.CONCRETE_STATUS_ICON) 552f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 553f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 554038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 555f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sCountProjectionMap = ProjectionMap.builder() 556f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(BaseColumns._COUNT, "COUNT(*)") 557f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 558f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 559e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 560f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionMap = ProjectionMap.builder() 561f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts._ID) 562f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 563f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.NAME_RAW_CONTACT_ID) 564f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 565f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsPresenceColumns) 566f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 567f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 568916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 569f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionWithSnippetMap = ProjectionMap.builder() 570f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 571f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sSnippetColumns) 572f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 573916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5745e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 575f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentStarredProjectionMap = ProjectionMap.builder() 576f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 577f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(TIMES_CONTACTED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 578f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 579f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 580f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder() 581f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 582f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(TIMES_CONTACTED_SORT_COLUMN, Contacts.TIMES_CONTACTED) 583f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 584f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 585f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 586f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsVCardProjectionMap = ProjectionMap.builder() 587f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME + " || '.vcf'") 588f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.SIZE, "NULL") 589f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 590f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 591ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 592f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactsProjectionMap = ProjectionMap.builder() 593f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 594f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 595f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 596f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_PRIMARY) 597f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_ALTERNATIVE) 598f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_SOURCE) 599f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME) 600f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME_STYLE) 601f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_PRIMARY) 602f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_ALTERNATIVE) 603f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.TIMES_CONTACTED) 604f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.LAST_TIME_CONTACTED) 605f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CUSTOM_RINGTONE) 606f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SEND_TO_VOICEMAIL) 607f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 608f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.AGGREGATION_MODE) 609f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 610f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 611f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 612f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 613a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the raw entity view*/ 614f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawEntityProjectionMap = ProjectionMap.builder() 615f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 616f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 617f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.Entity.DATA_ID) 618f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.IS_RESTRICTED) 619f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 620f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 621f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 622f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 623f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 624f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 625f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 626a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the contact entity view*/ 627f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sEntityProjectionMap = ProjectionMap.builder() 628f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity._ID) 629f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.CONTACT_ID) 630f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.RAW_CONTACT_ID) 631f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DATA_ID) 632f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.NAME_RAW_CONTACT_ID) 633f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DELETED) 634f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.IS_RESTRICTED) 635f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 636f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 637f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 638f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 639f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 640f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 641f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 642f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 644f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataProjectionMap = ProjectionMap.builder() 645f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID) 646f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RAW_CONTACT_ID) 647f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CONTACT_ID) 648f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.NAME_RAW_CONTACT_ID) 649f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 650f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 651f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 652f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 653f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 654f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 655f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 657f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDistinctDataProjectionMap = ProjectionMap.builder() 658f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID, "MIN(" + Data._ID + ")") 659f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 660f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 661f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 662f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 663f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 664f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 665f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6669261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 667f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sPhoneLookupProjectionMap = ProjectionMap.builder() 668f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup._ID, "contacts_view." + Contacts._ID) 669f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LOOKUP_KEY, "contacts_view." + Contacts.LOOKUP_KEY) 670f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.DISPLAY_NAME, "contacts_view." + Contacts.DISPLAY_NAME) 671f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LAST_TIME_CONTACTED, "contacts_view." + Contacts.LAST_TIME_CONTACTED) 672f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TIMES_CONTACTED, "contacts_view." + Contacts.TIMES_CONTACTED) 673f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.STARRED, "contacts_view." + Contacts.STARRED) 674f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.IN_VISIBLE_GROUP, "contacts_view." + Contacts.IN_VISIBLE_GROUP) 675f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.PHOTO_ID, "contacts_view." + Contacts.PHOTO_ID) 6763d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_URI, "contacts_view." + Contacts.PHOTO_URI) 6773d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_THUMBNAIL_URI, "contacts_view." + Contacts.PHOTO_THUMBNAIL_URI) 678f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.CUSTOM_RINGTONE, "contacts_view." + Contacts.CUSTOM_RINGTONE) 679f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.HAS_PHONE_NUMBER, "contacts_view." + Contacts.HAS_PHONE_NUMBER) 680f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.SEND_TO_VOICEMAIL, "contacts_view." + Contacts.SEND_TO_VOICEMAIL) 681f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.NUMBER, Phone.NUMBER) 682f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TYPE, Phone.TYPE) 683f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LABEL, Phone.LABEL) 6842530512f639c4979fd7371c7dd25dd67e8118124Bai Tao .add(PhoneLookup.NORMALIZED_NUMBER, Phone.NORMALIZED_NUMBER) 685f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 686f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 687ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 688f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsProjectionMap = ProjectionMap.builder() 689f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups._ID) 690f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_NAME) 691f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_TYPE) 692f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SOURCE_ID) 693f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DIRTY) 694f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.VERSION) 695f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.RES_PACKAGE) 696f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE) 697f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE_RES) 698f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.GROUP_VISIBLE) 699f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYSTEM_ID) 700f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DELETED) 701f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.NOTES) 702f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SHOULD_SYNC) 703f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.FAVORITES) 704f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.AUTO_ADD) 705c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov .add(Groups.GROUP_IS_READ_ONLY) 706f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC1) 707f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC2) 708f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC3) 709f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC4) 710f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 711f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 712ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 713f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsSummaryProjectionMap = ProjectionMap.builder() 714f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sGroupsProjectionMap) 715f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_COUNT, 716f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 717f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS 718f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP 719f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Clauses.BELONGS_TO_GROUP 720f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ")") 721f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_WITH_PHONES, 722f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 723f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS 724f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP 725f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Clauses.BELONGS_TO_GROUP 726f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ")") 727f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 728f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 729373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 730f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sAggregationExceptionsProjectionMap = ProjectionMap.builder() 731f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id") 732f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.TYPE) 733f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID1) 734f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID2) 735f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 736f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 737eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 738f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSettingsProjectionMap = ProjectionMap.builder() 739f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_NAME) 740f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_TYPE) 741f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_VISIBLE) 742f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.SHOULD_SYNC) 743f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ANY_UNSYNCED, 744f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 745f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ",(SELECT " 746f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "(CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL" 747f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 748f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE MIN(" + Groups.SHOULD_SYNC + ")" 749f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)" 750f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.GROUPS 751f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 752f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_NAME 753f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 754f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0" 755f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 756f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE 0" 757f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)") 758f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_COUNT, 759f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 760f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 761f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 762f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 763f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 764f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 765f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_WITH_PHONES, 766f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 767f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 768f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 769f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Contacts.HAS_PHONE_NUMBER 770f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 771f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 772f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 773f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 774f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 77582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 776f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStatusUpdatesProjectionMap = ProjectionMap.builder() 777f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PresenceColumns.RAW_CONTACT_ID) 778f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.DATA_ID, DataColumns.CONCRETE_ID) 779f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_ACCOUNT) 780f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_HANDLE) 781f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PROTOCOL) 782f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 783f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // properly enforce uniqueness of null values 784f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CUSTOM_PROTOCOL, 785f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL + "=''" 786f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN NULL" 787f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END)") 788f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PRESENCE) 789f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CHAT_CAPABILITY) 790f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS) 791f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_TIMESTAMP) 792f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_RES_PACKAGE) 793f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_ICON) 794f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_LABEL) 795f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 796f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 798f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sLiveFoldersProjectionMap = ProjectionMap.builder() 799f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders._ID, Contacts._ID) 800f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders.NAME, Contacts.DISPLAY_NAME) 801f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 802f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // for contacts without a photo 803f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // .add(LiveFolders.ICON_BITMAP, Photos.DATA) 804f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 805f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 806d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** Contains {@link Directory} columns */ 807f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDirectoryProjectionMap = ProjectionMap.builder() 808f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory._ID) 809f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.PACKAGE_NAME) 810f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.TYPE_RESOURCE_ID) 811f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DISPLAY_NAME) 812f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DIRECTORY_AUTHORITY) 813f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_TYPE) 814f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_NAME) 815f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.EXPORT_SUPPORT) 816778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.SHORTCUT_SUPPORT) 817778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.PHOTO_SUPPORT) 818f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 8197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 8209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 8219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 8229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 8239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 8249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 8259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 8262526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 8272526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 828bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 829bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 830bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 831bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 83251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 83303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_START_MATCH = "["; 83403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_END_MATCH = "]"; 83503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_ELLIPSIS = "..."; 83603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final int DEFAULT_SNIPPET_ARG_MAX_TOKENS = -10; 83703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 8389a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhoneInitialized; 8399a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhone; 8409a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 841f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 8421129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 8431129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 8442526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 8452526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 846f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 847f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 8484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 8494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 850a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 851d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 852d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 853a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA); 854a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES); 8553653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 8563653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 8572d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 8582d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 859a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO); 860c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); 8615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 8625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 8632149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA); 8645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 8652149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", 8662149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov CONTACTS_LOOKUP_ID_DATA); 867a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", 868a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ENTITIES); 869a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", 870a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ID_ENTITIES); 871f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 87242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 87342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 8745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 875ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 876ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 8775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 8783653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 8795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 8805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 8815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 88246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 88346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 88446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 885b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 8864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 8874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 888ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 88948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 8905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 891ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 8924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 89348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 8941dac83b8fa58944acfd00f44e717a7dddc659d2dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup", EMAILS_LOOKUP); 8955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 8965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 8974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 898ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 89948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 9001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 901ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 902ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 903ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 904ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 90535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 906b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 907b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 90835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 909a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 910b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 911b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 912b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 913b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 9144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 915eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 916eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 91782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 91882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 9191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 920c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 921c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 922c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 923c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 9242d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 925c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 926c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 9271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 9281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 9291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 9301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 9311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 9321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 9331b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 9341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 93509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 93609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 937d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 938d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories", DIRECTORIES); 939d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories/#", DIRECTORIES_ID); 9407a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 9417a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "complete_name", COMPLETE_NAME); 94219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 94319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 944d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static class DirectoryInfo { 945d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String authority; 946d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountName; 947d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountType; 948d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 949d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 950d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 951d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Cached information about contact directories. 952d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 9534458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private HashMap<String, DirectoryInfo> mDirectoryCache = new HashMap<String, DirectoryInfo>(); 9544458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private boolean mDirectoryCacheValid = false; 955d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 9563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 957ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 958ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 959ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 960e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov public static class GroupIdCacheEntry { 961ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 962ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 963ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 964ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 965ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 966a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 967e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 968e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 969e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // is a list of groups with this group id. 970e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 971e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov 9723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 973b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 97431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 9754097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 976f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 977315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 978622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 979622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 98072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private ContactDirectoryManager mContactDirectoryManager; 981622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 982f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 983a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 984d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 985f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private SearchIndexManager mSearchIndexManager; 986a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 98720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 98873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 98920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 99009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 9913826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private boolean mProviderStatusUpdateNeeded; 99209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 99315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mReadAccessLatch; 99415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mWriteAccessLatch; 99515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private boolean mAccountUpdateListenerRegistered; 996bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private boolean mOkToOpenAccess = true; 99773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 998d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private TransactionContext mTransactionContext = new TransactionContext(); 999de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 10001a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 10011a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 100281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 100381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 10044cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 10053826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private int mContactsAccountCount; 1006d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1007bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private HandlerThread mBackgroundThread; 1008bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private Handler mBackgroundHandler; 1009bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 10104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 10114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1012de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1013ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1014ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1015ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1016ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1017ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1018ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1019ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 102035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1021ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 102215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov StrictMode.setThreadPolicy( 102315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); 102415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 1025b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 102672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager = new ContactDirectoryManager(this); 1027a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 102865ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 1029bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // The provider is closed for business until fully initialized 103015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = new CountDownLatch(1); 103115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = new CountDownLatch(1); 103272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1033bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread = new HandlerThread("ContactsProviderWorker", 1034bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Process.THREAD_PRIORITY_BACKGROUND); 1035bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread.start(); 1036bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { 1037bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 1038bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void handleMessage(Message msg) { 1039bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov performBackgroundTask(msg.what, msg.obj); 1040bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1041bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov }; 10422a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 104315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_INITIALIZE); 1044bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1045bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 1046bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_LOCALE); 1047bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM); 104805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_SEARCH_INDEX); 1049bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_PROVIDER_STATUS); 105015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_OPEN_WRITE_ACCESS); 10513826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 105249d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov return true; 10534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 10544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1055767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 105651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 105751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 105804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 105915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 106015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 10614cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 106204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov mNameSplitter = mDbHelper.createNameSplitter(); 10634cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 10644cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 106551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mCommonNicknameCache = new CommonNicknameCache(mDbHelper.getReadableDatabase()); 1066cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 10675b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper, 106815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 10695b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1070f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSearchIndexManager = new SearchIndexManager(this); 10715b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 1072bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 1073bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1074bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, 10756d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForEmail(context, mDbHelper, mContactAggregator)); 1076bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 10776d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForIm(context, mDbHelper, mContactAggregator)); 1078bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, 10796d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForOrganization(context, mDbHelper, mContactAggregator)); 1080bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, 10816d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForPhoneNumber(context, mDbHelper, mContactAggregator)); 1082bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, 10836d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForNickname(context, mDbHelper, mContactAggregator)); 1084bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 10856d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForStructuredName(context, mDbHelper, mContactAggregator, 1086bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mNameSplitter, mNameLookupBuilder)); 1087bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 10886d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForStructuredPostal(context, mDbHelper, mContactAggregator, 1089bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mPostalSplitter)); 1090bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, 10916d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForGroupMembership(context, mDbHelper, mContactAggregator, 1092bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mGroupIdCache)); 1093bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, 10946d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForPhoto(context, mDbHelper, mContactAggregator)); 10956d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov mDataRowHandlers.put(Note.CONTENT_ITEM_TYPE, 10966d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForNote(context, mDbHelper, mContactAggregator)); 1097bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1098bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1099bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /** 1100bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Visible for testing. 1101bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov */ 1102bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 1103bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return new PhotoPriorityResolver(context); 1104bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1105bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1106bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task) { 1107bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendEmptyMessage(task); 1108bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1109bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1110bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task, Object arg) { 1111bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(task, arg)); 1112bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1113bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1114bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void performBackgroundTask(int task, Object arg) { 1115bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov switch (task) { 111615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_INITIALIZE: { 111715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov initForDefaultLocale(); 111815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch.countDown(); 111915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = null; 112015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov break; 112115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 112215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 112315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_OPEN_WRITE_ACCESS: { 1124bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (mOkToOpenAccess) { 112515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch.countDown(); 112615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = null; 1127bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1128bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1129bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1130bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1131bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS: { 1132bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1133bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov importLegacyContactsInBackground(); 1134bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1135bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1136bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1137bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1138bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_ACCOUNTS: { 113915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 114015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (!mAccountUpdateListenerRegistered) { 114115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov AccountManager.get(context).addOnAccountsUpdatedListener(this, null, false); 114215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mAccountUpdateListenerRegistered = true; 114315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 114415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 114515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Account[] accounts = AccountManager.get(context).getAccounts(); 1146bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean accountsChanged = updateAccountsInBackground(accounts); 1147bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateContactsAccountCount(accounts); 1148bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateDirectoriesInBackground(accountsChanged); 1149bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1150bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1151bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1152bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_LOCALE: { 1153bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateLocaleInBackground(); 1154bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1155bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1156bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1157fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov case BACKGROUND_TASK_CHANGE_LOCALE: { 1158fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov changeLocaleInBackground(); 1159fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov break; 1160fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1161fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1162bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM: { 1163bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isAggregationUpgradeNeeded()) { 1164bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov upgradeAggregationAlgorithmInBackground(); 1165bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1166bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1167bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1168bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 116905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_SEARCH_INDEX: { 117005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov updateSearchIndexInBackground(); 117105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov break; 117205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 117305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1174bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_PROVIDER_STATUS: { 1175bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateProviderStatus(); 1176bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1177bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1178bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1179bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_DIRECTORIES: { 1180bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (arg != null) { 1181bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.onPackageChanged((String) arg); 1182bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1183bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1184bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1185bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 11864cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 11874cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 118853fac8f99f3884c372c907a76766d27fa9e1d95fDmitri Plotnikov public void onLocaleChanged() { 11893826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 11903826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 11914f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov return; 11924f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov } 11934f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 1194fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_CHANGE_LOCALE); 11954cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 119651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 119751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 119851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 119951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 120051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 120151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 120251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 120351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 1204bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateLocaleInBackground() { 1205f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 1206f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 1207f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 1208f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 1209f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 1210f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 121151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 121251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 121351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 121451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 121551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 121651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 121751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 121851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 121951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 1220bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDbHelper.setLocale(this, currentLocale); 1221bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).apply(); 1222bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov setProviderStatus(providerStatus); 1223bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 122451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1225fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov /** 1226fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov * Reinitializes the provider for a new locale. 1227fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov */ 1228fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private void changeLocaleInBackground() { 1229fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Re-initializing the provider without stopping it. 1230fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Locking the database will prevent inserts/updates/deletes from 1231fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // running at the same time, but queries may still be running 1232fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // on other threads. Those queries may return inconsistent results. 1233fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getWritableDatabase(); 1234fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.beginTransaction(); 1235fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov try { 1236fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov initForDefaultLocale(); 1237fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.setTransactionSuccessful(); 1238fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } finally { 1239fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.endTransaction(); 1240fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1241fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1242fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov updateLocaleInBackground(); 1243fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1244fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 124505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov protected void updateSearchIndexInBackground() { 124605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mSearchIndexManager.updateIndex(); 124705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 124805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1249bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateDirectoriesInBackground(boolean rescan) { 1250bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanAllPackages(rescan); 125151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 125251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 12533826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateProviderStatus() { 12543826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 12553826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 12563826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return; 12573826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 12583826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 12593826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mContactsAccountCount == 0 126049d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov && DatabaseUtils.queryNumEntries(mDbHelper.getReadableDatabase(), 126149d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Tables.CONTACTS, null) == 0) { 12623826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 12633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } else { 12643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 12653826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 12663826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 12673826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 126831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1269de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1270b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1271b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 127231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 127331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1274013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1275013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1276013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1277013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 12785df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov /* package */ NameLookupBuilder getNameLookupBuilder() { 12795df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov return mNameLookupBuilder; 12805df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov } 12815df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov 12825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 1283ed78fd6df5e9f3a2d572162e5d374d1f4a625bddDmitri Plotnikov public ContactDirectoryManager getContactDirectoryManagerForTest() { 128472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return mContactDirectoryManager; 128572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 128672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 128772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 12885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 12895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 12905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 12915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 12923d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 1293b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 1294b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 12953d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 12963d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1297568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1298568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1299568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1300568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1301568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1302bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Imports legacy contacts as a background task. 1303568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1304bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private void importLegacyContactsInBackground() { 1305bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 1306bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 1307568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1308bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 1309bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDbHelper.setLocale(this, mCurrentLocale); 1310bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 1311568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1312bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1313bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (importLegacyContacts(importer)) { 1314bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportSuccess(); 1315bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } else { 1316bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportFailure(); 1317bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1318568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1319568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1320bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1321bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 1322bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1323bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 1324bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1325bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 1326bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 1327bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1328b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 1329b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDbHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 1330b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 1331bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 1332bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 1333bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1334bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1335bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1336bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 1337bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1338bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 1339bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 1340bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1341bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 1342bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1343bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 1344bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 1345bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 1346bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 1347bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 1348bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 1349bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 1350bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 1351bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 1352bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1353bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 1354bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1355bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 1356bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 1357bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1358bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // Do not let any database changes until this issue is resolved. 1359bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mOkToOpenAccess = false; 13603d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 13613d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 13623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1363568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 13640e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 13653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 13663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 1367bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 1368bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1369bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1370bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 1371bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 1372bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 13733d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 13743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 13753d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1376bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 1377bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 13783d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 13793d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1380a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1381a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1382a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1383a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1384b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 13853826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS; 1386a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1387a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1388568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 138915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov * During intialization, this content provider will 1390568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1391568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1392568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1393568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1394568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 139515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private void waitForAccess(CountDownLatch latch) { 139615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (latch == null) { 139715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 139815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 139915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 140015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov while (true) { 140115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov try { 140215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov latch.await(); 140315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 140415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } catch (InterruptedException e) { 140515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Thread.currentThread().interrupt(); 1406ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1407568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1408568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1409568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1410568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1411568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 141215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1413568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1414568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1415568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1416568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1417568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 141815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (mWriteAccessLatch != null) { 1419bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 1420bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 1421bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 1422bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 1423bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (match == PROVIDER_STATUS) { 1424bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 1425bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 1426bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1427bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 1428bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 1429bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 1430bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1431bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1432bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 143315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1434568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1435568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1436568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1437568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1438568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 143915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1440568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1441568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1442568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1443568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1444568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1445568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 144615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1447568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1448568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1449568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 14504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 14517b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov public int bulkInsert(Uri uri, ContentValues[] values) { 14527b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov waitForAccess(mWriteAccessLatch); 14537b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov return super.bulkInsert(uri, values); 14547b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov } 14557b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov 14567b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov @Override 1457285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1458bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1459b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1460b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1461285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 14621ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1463d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.clear(); 1464b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1465b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1466285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1467285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1468285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 14691129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 1470bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1471b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1472b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1473285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1474b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 14751ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 14761a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 14771a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 1478b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 14791a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 14803826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 14813826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatusUpdateNeeded) { 14823826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 14833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = false; 14843826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 1485b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1486b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1487b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1488bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1489b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1490b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 14911129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 1492d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov for (long rawContactId : mTransactionContext.getInsertedRawContactIds()) { 14937e2635fa663312adb2bc9d04f50a6bb54c6cc5f4Dmitri Plotnikov mContactAggregator.updateRawContactDisplayName(mDb, rawContactId); 1494d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mContactAggregator.onRawContactInsert(mDb, rawContactId); 1495285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1496b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1497d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov Set<Long> dirtyRawContacts = mTransactionContext.getDirtyRawContactIds(); 1498d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!dirtyRawContacts.isEmpty()) { 1499a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 1500a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 1501d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, dirtyRawContacts); 1502a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 1503a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 1504a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 1505a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1506d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov Set<Long> updatedRawContacts = mTransactionContext.getUpdatedRawContactIds(); 1507d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!updatedRawContacts.isEmpty()) { 1508a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 1509a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 1510d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, updatedRawContacts); 1511a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 1512a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 1513b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1514b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1515f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov Set<Long> staleRawContacts = mTransactionContext.getStaleSearchIndexRawContactIds(); 1516f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (!staleRawContacts.isEmpty()) { 1517f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSearchIndexManager.updateIndexForRawContacts(staleRawContacts); 1518f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 1519f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 1520d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov for (Map.Entry<Long, Object> entry : mTransactionContext.getUpdatedSyncStates()) { 1521b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 15229d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana if (mDbHelper.getSyncState().update(mDb, id, entry.getValue()) <= 0) { 15239d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 15249d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 15259d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 1526b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1527b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1528d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.clear(); 1529b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1530b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1531a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 1532a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 1533a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 1534a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 1535d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private void appendIds(StringBuilder sb, Set<Long> ids) { 1536b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 1537a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 1538b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1539a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1540a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 1541285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1542285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1543285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1544cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 154581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 154681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 154781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 154881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 154981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 155081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 155181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 1552cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 1553568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 155451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 15553826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != status) { 15563826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = status; 15573826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov getContext().getContentResolver().notifyChange(ProviderStatus.CONTENT_URI, null, false); 15583826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 155951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 156051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1561f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public DataRowHandler getDataRowHandler(final String mimeType) { 15623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 15633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 15646d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov handler = new DataRowHandlerForCustomMimetype( 15656d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov getContext(), mDbHelper, mContactAggregator, mimeType); 15663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 15673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 15693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 15714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1572de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 1573bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 15741129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 1575b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1576f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1577f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 1578f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 1579f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1580a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 1581a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 158235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1583a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 158435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 1585b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 158635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 158735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1588d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1589d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 15906bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 15916bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 15926bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 15935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 1594dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana id = insertRawContact(uri, values, callerIsSyncAdapter); 1595f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1596a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1597a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1598a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 15995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 16005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 1601f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1602f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1603a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1604a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1605a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1606a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 1607f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1608f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1609a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1610a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1611a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1612ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1613f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 1614f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1615ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1616ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1617ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1618eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 16195aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 162043880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 1621eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 1622eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 1623eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 162482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 162582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 16261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 16271f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 16281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1629a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 163081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 1631f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 1632a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1633a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 16347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 16357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 16367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 16377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1638de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 1639a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1640a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1641a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1642e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 1643e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 1644e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 1645e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 1646e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 1647e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 1648e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 1649e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 1650e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 1651e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 1652e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 1653e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 1654e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 16557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 1656e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 1657f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 1658f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 1659e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 1660f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1661f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 1662f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 1663e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 1664e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 1665e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1666e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 1667e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 1668fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 1669fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 1670e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 1671e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1672e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 1673e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 1674e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 1675e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 1676e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1677e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 1678e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 1679e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 1680e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 1681e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 1682fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 1683fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 1684e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 1685e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 1686e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 1687f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 1688f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 1689e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 1690f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 1691f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 1692e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 1693e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 1694f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 1695f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1696e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 1697f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 1698f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 1699f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 1700f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 1701035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1702f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1703e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 17047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 1707d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 17086bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 17096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 17106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 17116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1712d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 1713de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 17146bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 17156bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 17166bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 1717a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 1718a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1719f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 1720f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 1721dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param callerIsSyncAdapter 1722a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1723a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1724dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private long insertRawContact(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 1725f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 1726f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 1727f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 1728f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1729e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 17307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17313d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 17323d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 1733f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 17343d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 17353d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1736f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 1737f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 1738f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 1739f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 1740f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 1741f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId, aggregationMode); 1742285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1743285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 1744d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.rawContactInserted(rawContactId, account); 1745f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1746dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 1747dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 1748dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long starred = values.getAsLong(RawContacts.STARRED); 1749dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (starred != null && starred != 0) { 1750dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred != 0); 1751dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1752dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1753dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 17543826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 1755023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 1756a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1757a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1758dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void addAutoAddMembership(long rawContactId) { 1759dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID, 1760dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 1761dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 1762dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 1763dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1764dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1765dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1766dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private Long findGroupByRawContactId(String selection, long rawContactId) { 1767dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.GROUPS + "," + Tables.RAW_CONTACTS, PROJECTION_GROUP_ID, 1768dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, 1769dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}, 1770dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana null /* groupBy */, null /* having */, null /* orderBy */); 1771dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 1772dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 1773dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return c.getLong(0); 1774dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1775dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return null; 1776dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 1777dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 1778dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1779dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1780dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1781dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateFavoritesMembership(long rawContactId, boolean isStarred) { 1782dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID, 1783dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 1784dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 1785dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (isStarred) { 1786dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 1787dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 1788dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana deleteDataGroupMembership(rawContactId, groupId); 1789dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1790dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1791dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1792dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1793dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void insertDataGroupMembership(long rawContactId, long groupId) { 1794dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues groupMembershipValues = new ContentValues(); 1795dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.GROUP_ROW_ID, groupId); 1796dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 1797dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(DataColumns.MIMETYPE_ID, 1798dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDbHelper.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 1799dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.insert(Tables.DATA, null, groupMembershipValues); 1800dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1801dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1802dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void deleteDataGroupMembership(long rawContactId, long groupId) { 1803dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final String[] selectionArgs = { 1804dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(mDbHelper.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)), 1805dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(groupId), 1806dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(rawContactId)}; 1807dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs); 1808dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1809dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1810a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1811a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 1812a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1813a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1814a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1815a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1816f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 1817a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 1818de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 1819de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 182067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 1821de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 182220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1823de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 1824de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 1825de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 1826b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 1827de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 1828de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 1829508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 1830de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 1831de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 1832de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 1833de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 1834de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 18354097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 1836b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 1837de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 1838a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1839a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 1840d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov id = rowHandler.insert(mDb, mTransactionContext, rawContactId, mValues); 1841f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1842d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.markRawContactDirty(rawContactId); 1843a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1844d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.rawContactUpdated(rawContactId); 1845a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 18464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 18474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1848ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 18497e2635fa663312adb2bc9d04f50a6bb54c6cc5f4Dmitri Plotnikov mContactAggregator.updateRawContactDisplayName(db, rawContactId); 1850d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 1851d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 18529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 185320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 185420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 1855f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 185620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 185720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1858de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 1859de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 1860f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, 1861f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 1862de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 1863de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 1864f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID); 1865f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 1866a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 1867d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov count += rowHandler.delete(mDb, mTransactionContext, c); 1868f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1869d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.markRawContactDirty(rawContactId); 187088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 187120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 187220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 1873de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 187420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 187520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 187620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 187720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 187820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 187988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 188088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 188188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 188220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 1883f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 188488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 188588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 18864da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 1887f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, Data._ID + "=?", 18884da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 1889f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 189020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 189120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 189220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 189320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 189420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1895f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 189620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 189720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 189820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 189920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 190020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 190120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 190220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 190320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 190420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 19057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 190620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 190720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 190820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1909a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 1910d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov return rowHandler.delete(mDb, mTransactionContext, c); 191120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 191220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 191320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 191420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 191520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 191620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 1917ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 1918ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 1919f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 1920f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 1921f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 1922f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1923e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 1924ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1925ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 1926f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 192767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 1928f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 192967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 1930f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 1931ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1932dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final boolean isFavoritesGroup = mValues.getAsLong(Groups.FAVORITES) != null 1933dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ? mValues.getAsLong(Groups.FAVORITES) != 0 1934dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana : false; 1935dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1936f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1937f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 193873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 193973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1940f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 1941ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 1942dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && isFavoritesGroup) { 1943dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // add all starred raw contacts to this group 1944dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String selection; 1945dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs; 1946dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (account == null) { 1947dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + " IS NULL AND " 1948dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContacts.ACCOUNT_TYPE + " IS NULL"; 1949dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = null; 1950dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 1951dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + "=? AND " 1952dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContacts.ACCOUNT_TYPE + "=?"; 1953dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = new String[]{account.name, account.type}; 1954dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1955dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, 1956dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{RawContacts._ID, RawContacts.STARRED}, 1957dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, selectionArgs, null, null, null); 1958892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov try { 1959892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov while (c.moveToNext()) { 1960892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (c.getLong(1) != 0) { 1961892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov final long rawContactId = c.getLong(0); 1962892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov insertDataGroupMembership(rawContactId, result); 1963d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.markRawContactDirty(rawContactId); 1964892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 1965dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1966892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } finally { 1967892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov c.close(); 1968dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1969dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1970dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1971f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 19721a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 1973ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 1974ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 1975ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 1976ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1977ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 19785aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 1979e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 19805aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 19811a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 19821a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 1983e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 19841a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 1985e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 1986e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 1987e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 1988ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 198982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 19901f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 199182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 199282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 19930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 19944dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 19954dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 19960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 199782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 19984dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 19994dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 20004dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 20014dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 20021f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20031f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2004dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 2005dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 200682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 2007f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 20082526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 2009dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 2010dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 2011dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 20122526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 20132526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 20141f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 2015dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 2016dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 20170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 20180a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 20190a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 20200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2021dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 2022dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 2023dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 20242a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov String mimeTypeIdIm = String.valueOf(mDbHelper.getMimeTypeIdForIm()); 2025dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 20262a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov String mimeTypeIdEmail = String.valueOf(mDbHelper.getMimeTypeIdForEmail()); 2027f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2028f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 2029f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 2030f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 2031f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2032f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 2033f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 20342526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 20352526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 20362526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 20372526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 20382526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 20392526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 20402526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 20412526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 2042dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 20432526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 20442526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 2045dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 20462526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 20472526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 2048dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 20492526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 20502526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 20512526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 20522526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 20532526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 20542526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 2055dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 20562526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 20572526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 2058dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2059dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 20601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 206182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 20622526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 20632526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 2064dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 206570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 2066f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 206770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 20681f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 20691f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2070de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 20712526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 20724394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID); 20731f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 207467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 20755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2076e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 20771f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 20781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 20791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 20801f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20811f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 208231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 208331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 208431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 20851f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 208782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2088a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2089a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2090a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2091a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2092a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2093a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2094a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 209582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2096a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2097a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 209882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 209982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 210082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 210182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 210282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2103a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 210482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 210582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 2106aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori mValues.put(StatusUpdates.CHAT_CAPABILITY, 2107aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori values.getAsString(StatusUpdates.CHAT_CAPABILITY)); 21081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2109a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2110a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2111a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2112e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 21130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 211482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 211582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 21160a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 21170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 21180a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 21190a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 21200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 21210a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 21220a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 21230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 21240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 21250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 21260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 21270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2128a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 212978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.deleteStatusUpdate(dataId); 213082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 213182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 213278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.replaceStatusUpdate(dataId, timestamp, status, resPackage, iconResource, 213378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov labelResource); 2134a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 213578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.insertStatusUpdate(dataId, status, resPackage, iconResource, 213678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov labelResource); 2137e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2138e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2139bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2140a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2141f4015ab9ab7c26b766b5331fbf6655b8c54877eaDmitri Plotnikov mContactAggregator.updateLastStatusUpdateId(contactId); 2142a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2143a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2144a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 21451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 21461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 21474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2148de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2149bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2150b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2151b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2152b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2153f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2154f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2155508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2156508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 215735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2158b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 215935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2160b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2161b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2162b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2163b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2164b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2165b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2166cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2167cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2168cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2169cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2170cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2171d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2172d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2173dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 21746bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 21756bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 21769fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 21772e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 21782e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 21792e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 2180fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2181fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 21822e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 21832e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 21842e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 2185dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 21862e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 21872e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 21889fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 21899fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 21909fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 21919fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 21929fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 21939fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 2194a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 21959fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 21969fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 21979fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 21989fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 21999fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 22009fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 22019fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 22029fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 220360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 22049fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 22059fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 22069fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann Cursor c = query(db, lookupQb, null, selection, args, null, null, null); 22079fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 22089fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 22099fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 2210dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 22119fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 22129fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 22139fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 22149fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 22159fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 22169fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 22179fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 22189fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 22199fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 22209fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 22212971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 22222971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 2223fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, 2224fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 2225e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 22262971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 22272971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 22282971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2229fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 2230fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 2231fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 22322971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 22332971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 22342971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 22352971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 22362971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 22372971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 22382971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 22395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 22402971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2241fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return deleteRawContact(rawContactId, mDbHelper.getContactId(rawContactId), 2242fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 2243508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2244508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 224520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2246f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2247944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2248f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 224920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 225020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 225148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 225248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 225348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 225448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2255508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2256f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 22574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 22584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 2259ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2260ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2261ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2262f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 22635aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 22642971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 22652971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 22662971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 22672971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 22682971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2269e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 22702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 22712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 22725aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 22732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 22742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 22752971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 22762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 227781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2278f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 227981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 22802971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2281508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2282508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2283eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 228443880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2285e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 2286eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2287eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 228882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 22890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 22901f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 22911f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 229281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 229381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 22943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 229581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2296508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 22974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 22991c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 2300ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 2301b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 230294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2303de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 230494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 230594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 230694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 230794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2308f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2309de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 231094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 231194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 231294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2313f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2314de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 231594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 231694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 23171a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 231894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 231994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 232094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 23215aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2322e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 23231a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2324e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2325e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2326e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2327dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int deleteContact(long contactId, boolean callerIsSyncAdapter) { 232896b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 2329cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 233096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 233196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 2332cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2333cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2334cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2335dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 2336cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2337cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2338cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2339cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2340cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 23413826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 23423826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2343cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2344cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2345cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2346fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 23473389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 23483826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 23493826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2350f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 235114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2352fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov int count = mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 2353fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForContact(mDb, contactId); 2354fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 235533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2356b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 2357dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 235833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 235933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 236033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 23610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 23629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 23639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 23649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 23659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 23669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 23679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 23689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 23699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 23700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 23710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2372dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) { 237381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 237481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 2375cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 2376cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 2377cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2378cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2379cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2380cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2381dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues, callerIsSyncAdapter); 2382cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2383cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 23844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2385de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2386de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 2387bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2388b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2389b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2390b5a4add17815167d20a90645779df34cdf45280dFred Quintana 239135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 239200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 239300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 2394b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 2395b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 23961129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 2397d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.syncStateUpdated(rowId, data); 2398b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 2399b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2400b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2401f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2402f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 240300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 240435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2405b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2406b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 2407b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2408b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 2409b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 2410b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2411b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2412b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2413b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2414b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 2415b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 241635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2417d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2418dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 241900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 242000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 242100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 2422d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2423dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter); 2424c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 2425c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2426c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 24272e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 24282e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 24292e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 24302e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 24312e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 2432fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2433fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 24342e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 24352e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 24362e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 2437dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(contactId, values, callerIsSyncAdapter); 24382e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 24392e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 24402e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 24417d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 24427d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 24437d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 24447d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 24457d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 24467d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 24477d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 24487d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 24497d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 24507d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 245120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2452944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 2453f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 245481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2455f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 245681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 245720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 245820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2459c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 246048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 246148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 246248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 246348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2464f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 246581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2466f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 246781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 246800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 246900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 24707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 24715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 24725ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 2473dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, selection, selectionArgs, callerIsSyncAdapter); 24747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 24757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 24775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 247833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 24794529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 24804da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 24814da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 2482dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND(" + selection + ")", selectionArgs, 2483dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 24844529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 24854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 2486dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1, 2487dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 24884529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 24897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 24907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2492ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 24935aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 2494f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 249581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2496f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 249781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2498ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2499ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2500ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2501ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2502ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 25034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 25044da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 250573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 25065aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 25075aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 250881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 2509f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 251081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2511ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2512ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2513ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2514127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 2515de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 2516b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2517b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2518b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2519eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 2520e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 2521e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 252243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2523eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2524eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2525eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 25269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 25279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 25289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 25299705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25309705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 253172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case DIRECTORIES: { 2532bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanPackagesByUid(Binder.getCallingUid()); 253372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov count = 1; 2534d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 2535d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 2536d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 253781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 253881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2539f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 254081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 254100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 254200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 254300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 25444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 25454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 25469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 25479705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 25489705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 25499705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 25509705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 25519705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 25529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 25539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 25549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 25559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 25569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 25579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25599705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 25609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 25619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 25629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 25639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 25649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 25669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 25679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 25689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 25719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 25729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 25739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 25749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 25759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 25769705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 25779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 25789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 25799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 25829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 25839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 25849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 25859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 25869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 25879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 25889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 25899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 25909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 25919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 25929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 25939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 25949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 25979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 25989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 25999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 2600aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.CHAT_CAPABILITY, values, 2601aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori StatusUpdates.CHAT_CAPABILITY); 26029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 26039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 26049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 26055aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 2606f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 260773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2608ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 2609ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 261073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 2611f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 261273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 261373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 261473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 261573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 261673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 261773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 261873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 261973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2620ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 26211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 26221a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 262394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 26246ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 26251129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 26266ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 2627e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 26286ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 26296ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 26306ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 26316ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 26326ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 26336ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 26346ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 26356ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 26366ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 2637ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 26386ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 26396ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 26406ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 26416ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 26426ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 26436ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 26446ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 26456ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 264694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 264794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 264894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2649b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 2650b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 2651e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 26521a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 26531a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2654e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2655e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2656e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2657e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2658dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs, 2659dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 26604529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 26614529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 26624529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 26634529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 266473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 266597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 266697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 266797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0"); 266897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 266997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 26704529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 2671b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 267251bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 26734529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 26744529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 26754529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 26764529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 2677dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContact(rawContactId, values, callerIsSyncAdapter); 26784529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 26794529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26804529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 26814529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 26824529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 26844529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 26854529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 2687dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContact(long rawContactId, ContentValues values, 2688dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 268996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 269096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 269119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 269219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 269319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 2694ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 2695ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 269619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 269719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 269896b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1, null, null, null); 269919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 270019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 270119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 2702ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 2703ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 270419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 270519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 270619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 270719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 270819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 270919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 271019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 2711f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 271296b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker int count = mDb.update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 27135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 2714f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 2715f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 2716f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 2717f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 2718f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 2719f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 272069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode, false); 2721f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2722f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2723433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 2724dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 2725dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 2726dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana values.getAsLong(RawContacts.STARRED) != 0); 2727dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 27284529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 2729dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2730dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then update the 2731dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // favorites group membership based on whether or not this contact is starred. 2732dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // If it is starred, add a group membership, if one doesn't already exist 2733dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // otherwise delete any matching group memberships. 2734dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 2735dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean starred = 0 != DatabaseUtils.longForQuery(mDb, 2736dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SELECTION_STARRED_FROM_RAW_CONTACTS, 2737dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}); 2738dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred); 2739dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2740dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2741dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2742dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then add a 2743dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // group membership to the group marked as AutoAdd, if any. 2744dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 2745dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 2746433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 2747dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2748285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 27492b7a632bba423357ae5641f94da6a2f71afc523bDmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(mDb, rawContactId); 2750285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2751f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 2752f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 2753f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 2754f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 2755f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 275678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.resetNameVerifiedForOtherRawContacts(rawContactId); 2757f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 2758f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(mDb, rawContactId); 2759f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 276019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 2761d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.rawContactInserted(rawContactId, 2762d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov new Account(accountName, accountType)); 276319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 27645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 27655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 276633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 276733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 2768321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 2769f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 277020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 277120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 277220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 27735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 277420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 277520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 277620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 277720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 277820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2779b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 278020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 278120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 278297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 278397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 278497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov Data.IS_READ_ONLY + "=0"); 278597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 278697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 2787653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 278820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2789653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2790653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 2791f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(uri, DataRowHandler.DataUpdateQuery.COLUMNS, 2792f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 2793653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 2794653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 2795f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 279620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2797653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 2798653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 279920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 280020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2801653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 280220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 280320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2804f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 2805653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 2806653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 2807321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2808653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 2809f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String mimeType = c.getString(DataRowHandler.DataUpdateQuery.MIMETYPE); 2810a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2811d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (rowHandler.update(mDb, mTransactionContext, values, c, callerIsSyncAdapter)) { 2812813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 1; 2813813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } else { 2814813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 0; 2815a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 2816321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 2817321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 28188c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 2819dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 28208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 2821b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 28228c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 28238c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 28248c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 28258c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 28268c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 2827dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateContactOptions(contactId, values, callerIsSyncAdapter); 28288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 28298c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 28308c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 28318c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 28328c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 28338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 28348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 28358c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 28368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 2837dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateContactOptions(long contactId, ContentValues values, 2838dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 2839d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 28408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 2841b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 2842d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 2843b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 2844d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 2845b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 2846d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 2847b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 2848d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 2849b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 2850d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 2851d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2852d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 28538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 2854d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 2855d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2856d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 28578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 2858c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 28598c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 2860c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 2861c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 28624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 286397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?" 286497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov + " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1); 28658c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 2866dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) { 2867dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 2868dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?", 2869dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null, null, null); 2870dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 2871dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (cursor.moveToNext()) { 2872dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long rawContactId = cursor.getLong(0); 2873dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 2874dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.getAsLong(RawContacts.STARRED) != 0); 2875dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2876dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2877dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana cursor.close(); 2878dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2879dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2880dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 28818c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 28828c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 28838c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 2884b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 28858c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 2886b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 28878c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 2888b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 28898c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 2890b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 28918c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 2892b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 28938c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 28948c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 28959b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori int rslt = mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 28966e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 28979b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 28989b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 28999b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 29009b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 29019b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 29029b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 2903f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2904d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2905127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 2906127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 29070c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 29080c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 290980c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 2910ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId1; 2911ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId2; 29120c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 29130c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 29140c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 29150c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 29160c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 29170c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 2918b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2919127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 29200c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 29214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 29224da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 29230c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 29244da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 29254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 29260c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 29276bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 29286bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 29290c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 29300c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 29310c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 29320c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 2933127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2934127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 29353389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 293669cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1, 293769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 293869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2, 293969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 2940dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 29410dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1); 29420dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2); 2943127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2944127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 2945127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 2946127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 2947b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2948b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 294970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 2950bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 29513826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 29523826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2953bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected boolean updateAccountsInBackground(Account[] accounts) { 2954f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 2955e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov boolean accountsChanged = false; 2956627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 295749d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 295870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 295970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 2960dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana findValidAccounts(existingAccounts); 2961743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 2962743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // Add a row to the ACCOUNTS table for each new account 2963743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 2964743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov if (!existingAccounts.contains(account)) { 2965e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 2966743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 2967743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov + ", " + RawContacts.ACCOUNT_TYPE + ") VALUES (?, ?)", 2968743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov new String[] {account.name, account.type}); 2969743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 2970743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 297148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 2972627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 2973743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // in the accountsToDelete set will be extra accounts whose data must be deleted. 2974627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 2975627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 2976627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 297770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 297870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 297933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov if (!accountsToDelete.isEmpty()) { 2980e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 2981e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov for (Account account : accountsToDelete) { 2982e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov Log.d(TAG, "removing data for removed account " + account); 2983e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 2984e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 2985e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 2986e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 2987e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 2988e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 2989e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 2990e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 2991e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "SELECT " + RawContacts._ID + 2992e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 2993e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 2994e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 2995e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 2996e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 2997e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 2998e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 2999e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 3000e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 3001e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 3002e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 3003e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 3004e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 3005e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 3006e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + "=?", params); 3007d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mDb.execSQL( 3008d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov "DELETE FROM " + Tables.DIRECTORIES + 3009d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " WHERE " + Directory.ACCOUNT_NAME + "=?" + 3010d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " AND " + Directory.ACCOUNT_TYPE + "=?", params); 30114458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov resetDirectoryCache(); 3012e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 3013e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 301433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 301533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 3016e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov // names or photos. If so, fix up those contacts. 301733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 301833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Cursor cursor = mDb.rawQuery("SELECT " + Contacts._ID + 301933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 302033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 302169cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 302269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 302369cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 302433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 302533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 302669cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 302769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 302833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 302933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 303033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 303133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 303233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 303333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 303433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 303533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 303633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 303733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 303833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 3039e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDbHelper.updateAllVisible(); 304033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 304133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 3042e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (accountsChanged) { 3043e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 3044e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 304570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 304670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 304770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 304870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 304973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 30503826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 30513826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (accountsChanged) { 30523826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateContactsAccountCount(accounts); 30533826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 30543826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30553826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 3056afb84050536a4472c13efc0e996d31132d254605Dmitri Plotnikov return accountsChanged; 305770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3058619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 30593826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateContactsAccountCount(Account[] accounts) { 30603826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov int count = 0; 30613826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov for (Account account : accounts) { 30623826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (isContactsAccount(account)) { 30633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov count++; 30643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30653826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30663826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mContactsAccountCount = count; 30673826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30683826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 30693826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov protected boolean isContactsAccount(Account account) { 30703826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov final IContentService cs = ContentResolver.getContentService(); 30713826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov try { 30723826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return cs.getIsSyncable(account, ContactsContract.AUTHORITY) > 0; 30733826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } catch (RemoteException e) { 30743826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov Log.e(TAG, "Cannot obtain sync flag for account: " + account, e); 30753826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return false; 30763826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30773826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30783826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 307972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPackageChanged(String packageName) { 3080bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_DIRECTORIES, packageName); 3081d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3082d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3083619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3084627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 3085627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 3086dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void findValidAccounts(Set<Account> validAccounts) { 3087743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov Cursor c = mDb.rawQuery( 3088743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "SELECT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 3089743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " FROM " + Tables.ACCOUNTS, null); 3090627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 3091627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 3092dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!c.isNull(0) || !c.isNull(1)) { 3093627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 3094627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3095627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3096627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 3097627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 3098627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3099627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3100627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 31016ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov private static class DirectoryCursorWrapper extends CursorWrapper 31026ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov implements CrossProcessCursor { 31036ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov private final CrossProcessCursor mCrossProcessCursor; 31046ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 31056ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public DirectoryCursorWrapper(Cursor cursor, CrossProcessCursor crossProcessCursor) { 31066ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov super(cursor); 31076ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov mCrossProcessCursor = crossProcessCursor; 31086ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31096ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 31106ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov @Override 31116ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public void fillWindow(int pos, CursorWindow window) { 31126ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov mCrossProcessCursor.fillWindow(pos, window); 31136ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31146ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 31156ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov @Override 31166ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public CursorWindow getWindow() { 31176ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return mCrossProcessCursor.getWindow(); 31186ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31196ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 31206ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov @Override 31216ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public boolean onMove(int oldPosition, int newPosition) { 31226ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return mCrossProcessCursor.onMove(oldPosition, newPosition); 31236ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31246ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31256ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 31264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 31274f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 31284f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 312915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 313015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mReadAccessLatch); 313115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 3132d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY); 3133385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directory == null) { 3134385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov return queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1); 3135385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directory.equals("0")) { 3136385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov return queryLocal(uri, projection, selection, selectionArgs, sortOrder, 3137385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov Directory.DEFAULT); 3138d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } else if (directory.equals("1")) { 3139385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov return queryLocal(uri, projection, selection, selectionArgs, sortOrder, 3140385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov Directory.LOCAL_INVISIBLE); 3141d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3142d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3143d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryInfo directoryInfo = getDirectoryAuthority(directory); 3144d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo == null) { 3145a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov Log.e(TAG, "Invalid directory ID: " + uri); 3146a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov return null; 3147d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3148d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3149d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Builder builder = new Uri.Builder(); 3150d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.scheme(ContentResolver.SCHEME_CONTENT); 3151d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.authority(directoryInfo.authority); 3152d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.encodedPath(uri.getEncodedPath()); 3153d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountName != null) { 3154d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, directoryInfo.accountName); 3155d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3156d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountType != null) { 3157d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, directoryInfo.accountType); 3158d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 31592e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 31602e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limit = getLimit(uri); 31612e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov if (limit != null) { 31622e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov builder.appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, limit); 31632e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov } 31642e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 3165d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Uri directoryUri = builder.build(); 316609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 316709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (projection == null) { 316809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov projection = getDefaultProjection(uri); 316909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 317009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 3171332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov Cursor cursor = getContext().getContentResolver().query(directoryUri, projection, selection, 3172d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs, sortOrder); 31736ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 31746ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (cursor == null) { 31756ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 31766ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31776ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 31786ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov CrossProcessCursor crossProcessCursor = getCrossProcessCursor(cursor); 31796ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (crossProcessCursor != null) { 31806ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return new DirectoryCursorWrapper(cursor, crossProcessCursor); 31816ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else { 31826ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return matrixCursorFromCursor(cursor); 31836ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31846ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31856ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 31866ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov private CrossProcessCursor getCrossProcessCursor(Cursor cursor) { 31876ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov Cursor c = cursor; 31886ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (c instanceof CrossProcessCursor) { 31896ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return (CrossProcessCursor) c; 31906ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else if (c instanceof CursorWindow) { 31916ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return getCrossProcessCursor(((CursorWrapper) c).getWrappedCursor()); 31926ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else { 31936ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 31946ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31956ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31966ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 31976ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public MatrixCursor matrixCursorFromCursor(Cursor cursor) { 31986ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 31996ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov int numColumns = cursor.getColumnCount(); 32006ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov String data[] = new String[numColumns]; 32016ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov cursor.moveToPosition(-1); 32026ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov while (cursor.moveToNext()) { 32036ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov for (int i = 0; i < numColumns; i++) { 32046ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov data[i] = cursor.getString(i); 32056ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 32066ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov newCursor.addRow(data); 3207332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov } 32086ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return newCursor; 3209d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3210d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3211d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final class DirectoryQuery { 3212d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 3213d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory._ID, 3214d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.DIRECTORY_AUTHORITY, 3215d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_NAME, 3216d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_TYPE 3217d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov }; 3218d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3219d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int DIRECTORY_ID = 0; 3220d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int AUTHORITY = 1; 3221d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_NAME = 2; 3222d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_TYPE = 3; 3223d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3224d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3225d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 3226d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Reads and caches directory information for the database. 3227d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 3228d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private DirectoryInfo getDirectoryAuthority(String directoryId) { 32294458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized (mDirectoryCache) { 32304458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (!mDirectoryCacheValid) { 32314458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.clear(); 323249d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 323349d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Cursor cursor = db.query(Tables.DIRECTORIES, 32344458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryQuery.COLUMNS, 32354458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov null, null, null, null, null); 32364458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov try { 32374458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov while (cursor.moveToNext()) { 32384458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryInfo info = new DirectoryInfo(); 32394458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov String id = cursor.getString(DirectoryQuery.DIRECTORY_ID); 32404458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.authority = cursor.getString(DirectoryQuery.AUTHORITY); 32414458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME); 32424458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE); 32434458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.put(id, info); 32444458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 32454458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } finally { 32464458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov cursor.close(); 3247d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 32484458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = true; 3249d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3250d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 32514458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov return mDirectoryCache.get(directoryId); 32524458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 3253d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3254d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 325572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void resetDirectoryCache() { 32564458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized(mDirectoryCache) { 32574458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = false; 32584458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 325972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 326072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 3261d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public Cursor queryLocal(Uri uri, String[] projection, String selection, String[] selectionArgs, 3262385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov String sortOrder, long directoryId) { 3263bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3264bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 3265bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 32660b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 3267b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 326835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3269d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 32701f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 3271c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 3272c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3273619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 3274619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 3275a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 32764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 327735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3278b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 327935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 328035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3281d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3282763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3283385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov appendLocalDirectorySelectionIfNeeded(qb, directoryId); 3284619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 3285619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 3286619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3287d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 32884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3289763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 32904da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 32914da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 32926bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 32936bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 32946bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 32955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 32965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 32975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 32985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 32995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 3300fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3301fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 33025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 3303a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 33045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 33055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 33065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 33075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3308763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 3309a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3310a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 3311a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 3312a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 3313a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 33145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 33155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 3318763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 33194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 33204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 33214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 33225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 33235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 33245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 33252149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_DATA: 33262149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_ID_DATA: { 33272149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 33282149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov int segmentCount = pathSegments.size(); 33292149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount < 4) { 33302149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 33312149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov "Missing a lookup key", uri)); 33322149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 33332149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String lookupKey = pathSegments.get(2); 33342149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount == 5) { 33352149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 33362149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 33372149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(lookupQb, uri, projection, false); 3338a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 3339a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 3340a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 3341a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey); 3342a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 33432149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov return c; 33442149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 33452149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 33462149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov // TODO see if the contact exists but has no data rows (rare) 33472149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 33482149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 33492149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 33502149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 33512149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 33522149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov qb.appendWhere(" AND " + Data.CONTACT_ID + "=?"); 33532149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov break; 33542149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 33552149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 3356f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 3357f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 335842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 3359763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 3360f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 33614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 33624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 33634da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 3364f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 3365f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 3366f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 336742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 336842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 336942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 337042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return db.rawQuery( 337142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 337242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 337342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 337442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 337542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 337642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 3377ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 3378916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 3379ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 3380916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 3381ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3382916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet(qb, uri, projection, filterParam); 3383385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov appendLocalDirectorySelectionIfNeeded(qb, directoryId); 3384ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3385ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3386ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3387ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 3388ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 33894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 3390ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 3391d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 33924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 33934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3394e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 33955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 33964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 33974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 33984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3399763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3400ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 34015e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 34025e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 34035e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 3404dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov starredProjection = 3405dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov appendProjectionArg(projection, TIMES_CONTACTED_SORT_COLUMN); 3406dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov frequentProjection = 3407dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov appendProjectionArg(projection, TIMES_CONTACTED_SORT_COLUMN); 34085e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 34095e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 34104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 34114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 34124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3413d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 34145e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 34155e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 34164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3417d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3418d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 3419d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 3420763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 34214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 34224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 3423d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 34245e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 34255e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 3426d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 3427d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 34284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 3429d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3430d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 3431d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3432d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 34334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 34344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 3435d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 3436d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 3437d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3438d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 3439d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3440d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3441ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 3442763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 3443b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 344471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 34454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3446b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3447b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 3448b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3449b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3450a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_DATA: { 34514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 345282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 34534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 34544da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 34556bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 34566bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 345700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3458a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 34593653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 346082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 34614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 34624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 34633653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 34643653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 34653653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 34663653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 3467a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_ENTITIES: { 3468a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 3469a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 3470a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 3471a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 3472a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 3473a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3474a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3475a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ENTITIES: 3476a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ID_ENTITIES: { 3477a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 3478a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov int segmentCount = pathSegments.size(); 3479a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount < 4) { 3480a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3481a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov "Missing a lookup key", uri)); 3482a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3483a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lookupKey = pathSegments.get(2); 3484a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount == 5) { 3485a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 3486a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3487a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(lookupQb, uri, projection); 3488a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 3489a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3490a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 3491a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 3492a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.CONTACT_ID, contactId, 3493a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.LOOKUP_KEY, lookupKey); 3494a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 3495a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 3496a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3497a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3498a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3499a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 3500a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 3501a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 3502a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?"); 3503a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 3504a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3505a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 35064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 350782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 350889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 35092815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 35102815f58f72f109790585931f601a63ddc02536a5Evan Millar } 35112815f58f72f109790585931f601a63ddc02536a5Evan Millar 351248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 351382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 35144da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 351548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 35164da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 351748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 351848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 351948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3520ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 352182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 352289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3523ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 35244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 35254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 3526a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 35275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 352845d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 35295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 35305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 35315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 35325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 35337318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 35345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 353545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 35365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3538892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filterParam); 3539892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (!TextUtils.isEmpty(number)) { 35405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 35415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 35425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 3544892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov " IN (SELECT DISTINCT " + PhoneLookupColumns.DATA_ID 3545892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 3546892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 3547892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append(number); 3548892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append("%')"); 354945d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 355045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 355145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 355245d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 355345d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 355445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 355545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 35565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 3558a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 3559ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 35605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 3561a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3562a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3563a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 3564ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3565ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3566ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 35674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 356882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 356989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 35704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 35714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 35724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 357348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 357482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 35754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 35764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 35774da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 357848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 357948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 358048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 35815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 358282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 358389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 35844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 358508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 358608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String address = mDbHelper.extractAddressFromEmailAddress(email); 358708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 358808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 35894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3590ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3591ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3592ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 35935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 359482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 359507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 359607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 359707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 359807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 359907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 360007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 360107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 36025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 360307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 360407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 360507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 360607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 360707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 360807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 360907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 361007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 361107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 36122a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "="); 36132a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForEmail()); 36142a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(" AND " + Data.DATA1 + " LIKE "); 361507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 361620938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 361720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 361820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 361907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 362007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov /* 362107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * Using a UNION instead of an "OR" to make SQLite use the right 362207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * indexes. We need it to use the (mimetype,data1) index for the 362307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * email lookup (see above), but not for the name lookup. 362407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * SQLite is not smart enough to use the index on one side of an OR 362507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * but not on the other. Using two separate nested queries 362607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * and a UNION between them does the job. 362707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov */ 362807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 362907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " UNION SELECT " + Data._ID + 363007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 36312a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "="); 36322a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForEmail()); 36332a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(" AND " + Data.RAW_CONTACT_ID + " IN "); 36347318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 363520938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 36365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 3638a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 36395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 3641a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 3642c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov sortOrder = EMAIL_FILTER_SORT_ORDER; 3643a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 36445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 36455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3647ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 364882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 364989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 365089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3651ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 3652ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3653ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 365448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 365582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 36564da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 365748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 365848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 36594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 366048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 366148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 366248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 36635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 3664763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 36654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 36664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 36695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 3670763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 36714da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 36724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 36734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 36744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 36775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 367882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 36794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 36804da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 3681e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3682e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3683e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 3684e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 368582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3686e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 3687e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 3688e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 36894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 369082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 36914da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 36924da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 3693a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3694a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3695a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3696a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 36974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3698a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 3699a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 3700a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 3701892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sortOrder = " length(lookup.normalized_number) DESC"; 3702a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3703a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3704e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 3705e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov String numberE164 = PhoneNumberUtils.formatNumberToE164(number, 3706e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov mDbHelper.getCurrentCountryIso()); 3707892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String normalizedNumber = 3708892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.normalizeNumber(number); 3709892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, normalizedNumber, numberE164); 3710e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 3711e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 3712e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 3713e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 3714a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3715a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3716a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3717ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 3718b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3719ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 372089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3721ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3722ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3723ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3724ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3725b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3726ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 37274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 37284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 3729ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3730ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3731ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3732ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 3733b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 3734ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 373589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 373689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 3737ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3738ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3739ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3740b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 37410c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 3742b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 3743b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3744b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3745b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 374631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 3747d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 37482d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 37492d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 37502d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 37512d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 375231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 3753d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 3754d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 375531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 375631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 375731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 375831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 37595b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ArrayList<AggregationSuggestionParameter> parameters = null; 37605b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov List<String> query = uri.getQueryParameters("query"); 37615b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov if (query != null && !query.isEmpty()) { 37625b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters = new ArrayList<AggregationSuggestionParameter>(query.size()); 37635b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov for (String parameter : query) { 37645b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov int offset = parameter.indexOf(':'); 37655b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters.add(offset == -1 37665b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ? new AggregationSuggestionParameter( 376776dfa406e2cde19c824983c37fc92c1c5bf63eecDaniel Lehmann AggregationSuggestions.PARAMETER_MATCH_NAME, 37685b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter) 37695b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov : new AggregationSuggestionParameter( 37705b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(0, offset), 37715b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(offset + 1))); 37725b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 37735b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 37745b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 3775763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 37767581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 37777581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 37785b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov maxSuggestions, filter, parameters); 377931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 378031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3781eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3782eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 3783eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 378489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 3785e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3786e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 3787e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 3788b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 3789e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 379082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3791b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3792e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3793e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 379482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 3795b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3796e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3797e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3798e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3799eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3800eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3801eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 380282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 38030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 38045ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 38055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 38065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 380782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 38080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 38094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 38104da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 38115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 38125ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 38135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 3814c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 3815a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 3816c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3817c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3818c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 38192d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 38202d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill return mGlobalSearchSupport.handleSearchShortcutRefresh(db, lookupKey, projection); 3821c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3822c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 38231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 3824b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 38251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 38261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 38271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 38281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 3829b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 38301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 38311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 38321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 38331b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 38341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 3835b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 38361b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 38371b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 38381b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 38391b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 38401b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 3841b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 38421b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 384371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 38441b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 38451b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 38461b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 384746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 3848a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 384946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 385046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 385146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 385246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 385346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 3854a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 38554da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 38564da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 385746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 385846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 385946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 386009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 386109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 386209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 386309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 3864d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES : { 3865d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 3866d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 3867d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 3868d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3869d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3870d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID : { 3871385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov long id = ContentUris.parseId(uri); 3872d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 3873d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 3874385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(id)); 3875d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Directory._ID + "=?"); 3876d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 3877d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3878d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 38797a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov case COMPLETE_NAME: { 38807a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return completeName(uri, projection); 38817a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 38827a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 38834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 3884f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 3885c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 38864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 38874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 38887f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov qb.setStrictProjectionMap(true); 38897f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 3890ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 3891ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 3892ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 3893ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov cursor = bundleLetterCountExtras(cursor, db, qb, selection, selectionArgs, sortOrder); 3894ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3895ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 38965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 38975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 38985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 38995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 39005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 3901038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 3902038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 3903038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 3904038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 39055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 39065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 39074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 39084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 39094f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 39104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 39114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 39124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 391309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 391409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 391509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 391609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 391709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 391809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 391909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 392009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 392109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 392209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 392309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 392409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 392509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 392609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 392709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 392809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 3929a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 3930a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Runs the query with the supplied contact ID and lookup ID. If the query succeeds, 3931a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * it returns the resulting cursor, otherwise it returns null and the calling 3932a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * method needs to resolve the lookup key and rerun the query. 3933a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 3934a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private Cursor queryWithContactIdAndLookupKey(SQLiteQueryBuilder lookupQb, 3935a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteDatabase db, Uri uri, 3936a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection, String selection, String[] selectionArgs, 3937a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String sortOrder, String groupBy, String limit, 3938a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn, long contactId, String lookupKeyColumn, String lookupKey) { 3939a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] args; 3940a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (selectionArgs == null) { 3941a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[2]; 3942a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 3943a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[selectionArgs.length + 2]; 3944a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 3945a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3946a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[0] = String.valueOf(contactId); 3947a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[1] = Uri.encode(lookupKey); 3948a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(contactIdColumn + "=? AND " + lookupKeyColumn + "=?"); 3949a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 3950a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov groupBy, limit); 3951a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c.getCount() != 0) { 3952a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 3953a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3954a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3955a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov c.close(); 3956a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return null; 3957a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 395809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 3959bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 3960bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 3961bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 3962bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 3963ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3964bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 3965bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 3966ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 3967ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3968bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 3969bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 3970bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 3971bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 3972de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 3973ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3974ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3975ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 3976ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 3977ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 3978ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 3979ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 3980ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder) { 3981ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 3982ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3983ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 3984ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 3985ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 3986ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 3987ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 3988ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 3989ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 3990ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 3991ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 3992ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 3993ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 3994ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3995ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 3996ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 3997ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3998ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3999bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 4000ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 4001bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 4002bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "SUBSTR(" + sortKey + ",1,1) AS " + AddressBookIndexQuery.LETTER); 4003bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4004bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 4005bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 4006bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 4007bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 4008bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 4009bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 4010bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 4011ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 4012bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "GET_PHONEBOOK_INDEX(SUBSTR(" + sortKey + ",1,1),'" + locale + "')" 4013bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 4014ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 4015ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov "COUNT(" + Contacts._ID + ") AS " + AddressBookIndexQuery.COUNT); 4016ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 4017ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4018f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 4019ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 4020ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 4021ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4022ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 4023f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 4024ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 4025ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 4026bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 4027bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 4028bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4029bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 4030bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 4031bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 4032ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 4033f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 4034bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 4035bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 4036bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 4037bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 4038bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 4039bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 4040bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 4041bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 4042bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4043bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4044bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4045bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 4046bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 4047bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 4048bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 4049bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4050bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 4051bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 4052bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 4053ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4054ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4055e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov return new AddressBookCursor((CrossProcessCursor) cursor, titles, counts); 4056ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 4057f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 4058ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4059ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4060ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 40612d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 406292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 406392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 406492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 406592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 40662d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 40672d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 40685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 40695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 40705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 407192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 407292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 407392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 407492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 407592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 407692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 407792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 407892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 407992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 408092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 408192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 408292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 408392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 408492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 408592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 408692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 408792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 408892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 408992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 40905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 40915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 40945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 40975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 40985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 41005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 41015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 41025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 41035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 41045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 41055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 41075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 41085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 41095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 41105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 41135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 41145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 41155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 41165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 41175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 411892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 41195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 41205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 41215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 41245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 41255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 41275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 41285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 41295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 41305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 41315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 41325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 41335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 41345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 41355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 41365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 413792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 413892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 41395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 41405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 41415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 41425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 41465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 41475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 41505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 415292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 415392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 41545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 41565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 41575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 41585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 415992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 41605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 41615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 41635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 41645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 416592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 41665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 416892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 416992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 417092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 417192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 41725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 41735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 417492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 417592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 417692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 41775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 417992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 418092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 41815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 418292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 418392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 418492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 418592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 418692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountType = c.getString(LookupByRawContactIdQuery.ACCOUNT_TYPE); 418792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 418892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 418992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 419092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 419192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 419292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 419392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 419492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 419592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 419692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 419792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 419892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 419992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 420092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 420192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 420292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 42035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 420592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 420692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 420792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 420892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 420992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 421092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 421192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 421292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 421392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 421492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 421592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 421692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 421792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 421892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 421992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_TYPE = 1; 422092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 422192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 422292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 422392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 422492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 422592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 42265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 42275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 42285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 42295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 423092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 423192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 42325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 42335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 42345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 42375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 42385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 42395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 42415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 42425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 42435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 42445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 42455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 42465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 42475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 42485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 42495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 42505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 425192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 425292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 425392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 42545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 42555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 42565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 42575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 42615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 42625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 42655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 426792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 426892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 426992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 427092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 427192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 427292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 427392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 427492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 427592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 427692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 427792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 4278ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 4279ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(db, rawContactId); 4280ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 4281ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 42825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 42835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 42845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 42855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 42865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 42875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 42895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 42905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 42925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 42935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 42955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 42965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 42975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 42985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 42995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 43005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 43015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 43025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 43035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 43045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 43065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 43075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 43115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 43125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 43135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 43145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4317763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 4318763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 431982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4320916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 4321916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 4322916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 4323916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4324916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4325916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 4326916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 4327916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 4328916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 4329916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 4330916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String[] projection, String filter) { 4331916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 433203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (filter != null) { 433303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov filter = filter.trim(); 433403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 433503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 4336916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4337916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 433803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov appendSearchIndexJoin(sb, uri, projection, filter); 433903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setTables(sb.toString()); 434003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 434103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 4342916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 434303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private void appendSearchIndexJoin( 434403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov StringBuilder sb, Uri uri, String[] projection, String filter) { 434503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(" JOIN (SELECT " + SearchIndexColumns.CONTACT_ID + " AS snippet_contact_id"); 4346916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 434703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET)) { 434803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String startMatch; 434903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String endMatch; 435003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String ellipsis; 435103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov int maxTokens; 4352916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 435303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String[] args = null; 435403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String snippetArgs = 435503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 435603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (snippetArgs != null) { 435703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov args = snippetArgs.split(","); 435803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 435903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 436003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (args != null && args.length > 0) { 436103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov startMatch = args[0]; 436203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 436303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov startMatch = DEFAULT_SNIPPET_ARG_START_MATCH; 436403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 436503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 436603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (args != null && args.length > 1) { 436703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov endMatch = args[1]; 436803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 436903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov endMatch = DEFAULT_SNIPPET_ARG_END_MATCH; 437003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 437103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 437203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (args != null && args.length > 2) { 437303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov ellipsis = args[2]; 437403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 437503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov ellipsis = DEFAULT_SNIPPET_ARG_ELLIPSIS; 437603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 4377916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 437803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (args != null && args.length > 3) { 437903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov maxTokens = Integer.parseInt(args[3]); 438003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 438103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov maxTokens = DEFAULT_SNIPPET_ARG_MAX_TOKENS; 438203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 438303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 438403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(", " + "snippet(" + Tables.SEARCH_INDEX + ","); 438503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 438603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(","); 438703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 438803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(","); 438903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, ellipsis); 439003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 439103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov // The index of the column used for the snippet, "content" 439203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(",1,"); 439303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(maxTokens); 439403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(")" + " AS " + SearchSnippetColumns.SNIPPET); 4395916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4396916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 439703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(" FROM " + Tables.SEARCH_INDEX + " WHERE "); 439803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 439903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (TextUtils.isEmpty(filter)) { 440003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append("0"); // Empty filter - return an empty set 440103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 440203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(Tables.SEARCH_INDEX + " MATCH "); 440303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filter + "*"); 44049c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 440503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(") ON (" + Contacts._ID + "=snippet_contact_id)"); 44069c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov 440703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (true) { 440803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov return; 4409916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4410916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 441103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (filter.indexOf('@') != -1) { 441203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String address = mDbHelper.extractAddressFromEmailAddress(filter); 441303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (!TextUtils.isEmpty(address)) { 441403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(DataColumns.CONCRETE_ID + " IN (" + 441503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov "SELECT MIN(" + DataColumns.CONCRETE_ID + ")" + 441603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov " FROM " + Tables.DATA_JOIN_MIMETYPE_RAW_CONTACTS + 441703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + " IN ("); 441803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForEmail()); 441903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(","); 442003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForIm()); 442103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(","); 442203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForSip()); 442303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(") AND " + Data.DATA1 + " LIKE("); 442403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, address + '%'); 442503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(")" + 442603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov " GROUP BY " + RawContactsColumns.CONCRETE_CONTACT_ID + 442703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov ")"); 442803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov return; 442903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 4430916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4431916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 443203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String normalizedFilter = NameNormalizer.normalize(filter); 443303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (!TextUtils.isEmpty(normalizedFilter)) { 443403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(DataColumns.CONCRETE_ID + " IN ("); 4435c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov 443603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov // Construct a query that gives us exactly one data _id per matching contact. 443703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov // MIN stands in for ANY in this context. 443803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append( 443903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov "SELECT MIN(" + Tables.NAME_LOOKUP + "." + NameLookupColumns.DATA_ID + ")" + 444003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 444103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 444203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov " ON (" + RawContactsColumns.CONCRETE_ID 444303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov + "=" + Tables.NAME_LOOKUP + "." 444403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 444503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + " GLOB '"); 444603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(normalizedFilter); 444703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 444803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + ")" + 444903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov " GROUP BY " + RawContactsColumns.CONCRETE_CONTACT_ID + 445003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov ")"); 445103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 445203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append("0"); // Empty filter - return an empty set 445303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 4454a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov 445503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (isPhoneNumber(filter)) { 445603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filter); 445703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(" OR " + DataColumns.CONCRETE_ID + " IN (" + 445803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov " SELECT DISTINCT " + PhoneLookupColumns.DATA_ID 445903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 446003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 446103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(number); 446203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append("%'"); 4463a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov 446403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String numberE164 = PhoneNumberUtils.formatNumberToE164(number, 446503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov mDbHelper.getCountryIso()); 446603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (!TextUtils.isEmpty(numberE164)) { 446703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(" OR " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 446803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(numberE164); 446903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append("%'"); 447003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 447103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(')'); 447203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 4473a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov } 4474a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov 4475916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void appendContactsTables(StringBuilder sb, Uri uri, String[] projection) { 4476763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4477f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4478763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4479763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4480d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4481763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4482763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 4483a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 4484a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 448582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 4486ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 4487763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 4488763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 4489763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 4490f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4491763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4492763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 4493d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4494763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4495763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 4496763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 4497763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 4498763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 4499763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 4500763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 4501a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForRawEntities(SQLiteQueryBuilder qb, Uri uri) { 4502a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(mDbHelper.getRawEntitiesView(shouldExcludeRestrictedData(uri))); 4503a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sRawEntityProjectionMap); 450446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 450546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 450646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 450782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 450882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 450982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4510a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(mDbHelper.getDataView(shouldExcludeRestrictedData(uri))); 451182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 451282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 4513a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, RawContacts.CONTACT_ID); 4514a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 4515a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 4516a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 45173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 451882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 4519f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 4520f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov boolean useDistinct = distinct 4521f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov || !mDbHelper.isInProjection(projection, DISTINCT_DATA_PROHIBITING_COLUMNS); 4522f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setDistinct(useDistinct); 4523f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setProjectionMap(useDistinct ? sDistinctDataProjectionMap : sDataProjectionMap); 452482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 4525ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 4526ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 45270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 45280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 45290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4530b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 45310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 4532a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 4533a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 45340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4535a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 4536a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 4537a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4538a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4539a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForEntities(SQLiteQueryBuilder qb, Uri uri, 4540a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection) { 4541a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4542a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(mDbHelper.getEntitiesView(shouldExcludeRestrictedData(uri))); 4543a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" data"); 4544a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4545a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts.Entity.CONTACT_ID); 4546a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 4547a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, Contacts.Entity.DATA_ID); 4548a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, Contacts.Entity.DATA_ID); 4549a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4550a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 4551a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sEntityProjectionMap); 4552a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4553a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4554a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4555a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactStatusUpdateJoin(StringBuilder sb, String[] projection, 4556a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lastStatusUpdateIdColumn) { 4557a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 4558a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS, 4559a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 4560a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 4561a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 4562a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 4563a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 4564a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 4565a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + lastStatusUpdateIdColumn + "=" 4566a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 45670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 4568a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 45690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4570a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataStatusUpdateJoin(StringBuilder sb, String[] projection, 4571a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 4572b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 45730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 45740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 45750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 45760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 45770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 45780a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 4579a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 4580a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + dataIdColumn + ")"); 45810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 4582a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4583a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4584a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactPresenceJoin(StringBuilder sb, String[] projection, 4585a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn) { 4586a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 4587a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_PRESENCE, Contacts.CONTACT_CHAT_CAPABILITY)) { 4588a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 4589a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + contactIdColumn + " = " 4590a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + ")"); 4591a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4592a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4593a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4594a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataPresenceJoin(StringBuilder sb, String[] projection, 4595a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 4596a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.PRESENCE, Data.CHAT_CAPABILITY)) { 4597a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 4598a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdates.DATA_ID + "=" + dataIdColumn + ")"); 4599a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4600a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4601a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4602385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov private void appendLocalDirectorySelectionIfNeeded(SQLiteQueryBuilder qb, long directoryId) { 4603385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directoryId == Directory.DEFAULT) { 4604385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " IN " + Tables.DEFAULT_DIRECTORY); 4605385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directoryId == Directory.LOCAL_INVISIBLE){ 4606385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " NOT IN " + Tables.DEFAULT_DIRECTORY); 4607385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } 4608385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } 4609385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov 4610a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private boolean shouldExcludeRestrictedData(Uri uri) { 4611a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov // Note: currently, "export only" equals to "restricted", but may not in the future. 4612a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov boolean excludeRestrictedData = readBooleanQueryParameter(uri, 4613a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.FOR_EXPORT_ONLY, false); 4614a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (excludeRestrictedData) { 4615a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return true; 4616a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4617a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4618a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String requestingPackage = getQueryParameter(uri, 4619a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 4620a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (requestingPackage != null) { 4621a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return !mDbHelper.hasAccessToRestrictedData(requestingPackage); 4622a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4623a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4624a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return false; 46250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 46260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 46274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 4628f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 4629f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 4630e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4631e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 4632e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 4633e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 4634fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4635fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 4636e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4637e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4638e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 4639e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 4640e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 4641e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 46424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 46434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 46444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 46454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 46464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 46474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 46484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 46494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 46504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4651e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 4652f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 4653f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 4654e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4655e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 4656e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 4657e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 4658fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4659fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 4660e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4661e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4662e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 4663e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 4664e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 4665e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 4666e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 4667e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4668e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 4669e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 4670e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 4671e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 4672e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 4673e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 4674e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4675e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 4676e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 4677e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 4678e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4679e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 4680e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 46817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 4682c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 4683c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 4684c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 4685c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 4686c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 4687f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 46882e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limitParam = getQueryParameter(uri, ContactsContract.LIMIT_PARAM_KEY); 4689c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 4690c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4691c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4692c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 4693c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 4694c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 4695c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 4696c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4697c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4698c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4699c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 4700c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 4701c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 4702c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 4703c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4704c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4705c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 470600ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 4707d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 470870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 470970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 4710fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0"; 471170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 471270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 471370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 471470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 4715d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 471670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 471767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 47185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 47195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 4720619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4721619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4722619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4723b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 4724f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 4725415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 4726415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov waitForAccess(mReadAccessLatch); 4727415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 4728b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 4729b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 4730a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 4731f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return openPhotoAssetFile(uri, mode, 4732e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=" + Contacts.PHOTO_ID + " AND " + RawContacts.CONTACT_ID + "=?", 4733e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 4734e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 4735b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4736e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 4737f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return openPhotoAssetFile(uri, mode, 4738e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=? AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'", 47394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 4740d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4741d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4742f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 474349d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 474442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 474549d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(lookupContactIdByLookupKey(db, lookupKey)); 474642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + "=?"; 474742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 474842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 474942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 475042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 475142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 475242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann outputRawContactsAsVCard(localStream, selection, mSelectionArgs1); 4753f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 475442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 475542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 475642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 475749d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 475842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 475942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 476042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 476142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 4762d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 4763d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 476442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 476542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 4766d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 476742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 4768d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 476942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 477049d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov inBuilder.append(lookupContactIdByLookupKey(db, lookupKey)); 477142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 477242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 477342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 477442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 4775d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4776d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 4777d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 4778d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 4779d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 4780d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann outputRawContactsAsVCard(localStream, selection, null); 4781f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 4782d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4783b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4784b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 4785fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("File does not exist", 4786fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov uri)); 4787b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4788b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4789b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 4790f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor openPhotoAssetFile(Uri uri, String mode, String selection, 4791e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String[] selectionArgs) 4792e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 4793e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 4794e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("Mode " + mode 4795e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 4796e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 4797e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 4798e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 4799e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 4800e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 4801e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 480208ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood try { 4803f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 4804f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert DatabaseUtils.blobFileDescriptorForQuery(db, sql, selectionArgs)); 480508ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } catch (SQLiteDoneException e) { 480608ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood // this will happen if the DB query returns no rows (i.e. contact does not exist) 480708ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood throw new FileNotFoundException(uri.toString()); 480808ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } 4809e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 4810e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 4811d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 4812d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4813d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4814f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert * Returns an {@link AssetFileDescriptor} backed by the 4815d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 4816d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4817f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 4818d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 4819d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 4820d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4821d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 4822d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4823f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 4824f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert ParcelFileDescriptor.fromData(byteData, CONTACT_MEMORY_FILE_NAME), 4825f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert byteData.length); 4826d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 4827ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert Log.w(TAG, "Problem writing stream into an ParcelFileDescriptor: " + e.toString()); 4828ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return null; 4829d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4830d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4831d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4832f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd) { 4833f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor(fd, AssetFileDescriptor.UNKNOWN_LENGTH); 4834f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 4835f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 4836f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd, long length) { 4837f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return fd != null ? new AssetFileDescriptor(fd, 0, length) : null; 4838f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 4839f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 4840d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 4841d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 4842d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 4843d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 4844d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 4845d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 4846d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 4847d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 48487a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 48497a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa new VCardComposer(context, VCardConfig.VCARD_TYPE_DEFAULT, false); 4850d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 4851d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4852f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 48537a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa if (!composer.init(selection, selectionArgs)) { 48547a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 4855d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 48567a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa } 4857d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4858d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 4859d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 4860d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 4861d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4862d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4863d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 4864d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4865b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 48664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 48674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 4868415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 4869415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov waitForAccess(mReadAccessLatch); 4870415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 4871a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 48724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 4873b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 4874be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 48752d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 4876b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 4877b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 4878b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 4879f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 488042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 4881f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 4882f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov case CONTACTS_ID_PHOTO: 4883f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov return "image/png"; 4884b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 4885be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 4886b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 4887b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 4888f481f22a9323fe338672f99b88b26c5f0725cd42David Brown case DATA: 4889f481f22a9323fe338672f99b88b26c5f0725cd42David Brown return Data.CONTENT_TYPE; 4890508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 4891b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 489248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 489348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 489448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 489548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 48969005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 48979005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 489848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 489948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 490048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 490148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 490248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 490348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 490448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 490548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 4906b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 4907b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 4908b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 4909b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 4910b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 4911b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 4912b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 4913b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 4914c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 4915c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 4916c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 4917c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 4918d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES: 4919d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_TYPE; 4920d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID: 4921d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_ITEM_TYPE; 492261efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 492361efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 49244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 49254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 49267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 492709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public String[] getDefaultProjection(Uri uri) { 492809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov final int match = sUriMatcher.match(uri); 492909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov switch (match) { 493009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS: 493109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP: 493209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_ID: 493309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP_ID: 493409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 493509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsProjectionMap.getColumnNames(); 493609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 49378727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov case CONTACTS_ID_ENTITIES: 49388727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov return sEntityProjectionMap.getColumnNames(); 49398727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov 494009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_VCARD: 494109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_MULTI_VCARD: 494209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsVCardProjectionMap.getColumnNames(); 494309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 494409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS: 494509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS_ID: 494609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sRawContactsProjectionMap.getColumnNames(); 494709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 494809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DATA_ID: 494909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES: 495009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES_ID: 495109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS: 495209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS_ID: 495309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS: 495409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS_ID: 495509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDataProjectionMap.getColumnNames(); 495609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 495709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONE_LOOKUP: 495809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sPhoneLookupProjectionMap.getColumnNames(); 495909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 496009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 496109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 496209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sAggregationExceptionsProjectionMap.getColumnNames(); 496309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 496409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case SETTINGS: 496509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sSettingsProjectionMap.getColumnNames(); 496609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 496709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES: 496809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES_ID: 496909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDirectoryProjectionMap.getColumnNames(); 497009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 497109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov default: 497209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return null; 497309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 497409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 497509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 4976f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 4977f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4978f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 4979f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 4980f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4981f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4982f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4983f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 4984f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 498578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.insertNameLookup(rawContactId, dataId, lookupType, name); 4986f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4987f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 4988f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 4989f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 4990d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 4991f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4992f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 4993f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 49942d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 4995d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 4996d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 4997d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4998d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 4999d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 5000d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 5001d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 5002e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 5003916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 5004916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 5005e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 5006e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 50075ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 5008c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 50097318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam); 5010c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 5011c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5012c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 50137318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam) { 50147318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), true); 50155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 50165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 50175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 50187318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov boolean allowEmailMatch) { 501923061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov if (TextUtils.isEmpty(normalizedName)) { 502023061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov // Effectively an empty IN clause - SQL syntax does not allow an actual empty list here 502123061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append("(0)"); 502223061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov } else { 502323061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append("(" + 502423061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov "SELECT " + NameLookupColumns.RAW_CONTACT_ID + 502523061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 502623061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 502723061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov " GLOB '"); 502823061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov // Should not use a "?" argument placeholder here, because 502923061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov // that would prevent the SQL optimizer from using the index on NORMALIZED_NAME. 503023061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append(normalizedName); 503123061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 503223061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 503323061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov + NameLookupType.NICKNAME + "," 503423061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov + NameLookupType.NAME_SHORTHAND + "," 503523061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov + NameLookupType.ORGANIZATION + "," 503623061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov + NameLookupType.NAME_CONSONANTS); 503723061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov if (allowEmailMatch) { 503823061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 503923061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov } 504023061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov sb.append("))"); 504123061012b777c607100ce30250c3542b4fc8c1c8Dmitri Plotnikov } 5042ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5043ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 50449a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 50459a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov public boolean appendEmailBasedDataFilter(StringBuilder sb, String filter) { 50469a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (filter.indexOf('@') == -1) { 50479a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 50489a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 50499a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 50509a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov String address = mDbHelper.extractAddressFromEmailAddress(filter); 50519a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (TextUtils.isEmpty(address)) { 50529a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 50539a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 50549a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 50559a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(DataColumns.MIMETYPE_ID + " IN ("); 50569a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForEmail()); 50579a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(","); 50589a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForIm()); 50599a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(","); 50609a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForSip()); 50619a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(") AND " + Data.DATA1 + " LIKE("); 50629a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, address + '%'); 50639a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(")"); 50649a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return true; 50659a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 50669a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 50679a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov public boolean appendPhoneNumberBasedDataFilter(StringBuilder sb, String filter) { 50689a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (!isPhoneNumber(filter)) { 50699a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 50709a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 50719a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 50729a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filter); 50739a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(DataColumns.CONCRETE_ID + " IN " + 50749a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov "(SELECT " + PhoneLookupColumns.DATA_ID 50759a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 50769a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 50779a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(number); 50789a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append("%'"); 50799a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 50809a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov String numberE164 = PhoneNumberUtils.formatNumberToE164(number, mDbHelper.getCountryIso()); 50819a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (!TextUtils.isEmpty(numberE164)) { 50829a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(" OR " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 50839a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(numberE164); 50849a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append("%'"); 50859a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 50869a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(")"); 50879a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 50889a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov String normalizedFilter = NameNormalizer.normalize(filter); 50899a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (TextUtils.isEmpty(normalizedFilter)) { 50909a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return true; 50919a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 50929a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 50939a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(" OR " + DataColumns.CONCRETE_RAW_CONTACT_ID + " IN " + 50949a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov "(SELECT " + NameLookupColumns.RAW_CONTACT_ID + 50959a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 50969a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 50979a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov " GLOB '"); 50989a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(normalizedFilter); 50999a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 51009a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov + CONTACT_LOOKUP_NAME_TYPES + "))"); 51019a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return true; 51029a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 51039a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 51049a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov public boolean appendNameBasedRawContactFilter(StringBuilder sb, String filter) { 51059a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov String normalizedFilter = NameNormalizer.normalize(filter); 51069a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (TextUtils.isEmpty(normalizedFilter)) { 51079a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 51089a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 51099a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 51109a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(DataColumns.CONCRETE_RAW_CONTACT_ID + " IN " + 51119a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov "(SELECT " + NameLookupColumns.RAW_CONTACT_ID + 51129a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 51139a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 51149a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov " GLOB '"); 51159a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov // Should not use a "?" argument placeholder here, because 51169a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov // that would prevent the SQL optimizer from using the index on NORMALIZED_NAME. 51179a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append(normalizedFilter); 51189a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 51199a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov + CONTACT_LOOKUP_NAME_TYPES + "))"); 51209a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return true; 51219a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 51229a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 51239a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov public boolean isPhoneNumber(String filter) { 51249a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean atLeastOneDigit = false; 51259a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov int len = filter.length(); 51269a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov for (int i = 0; i < len; i++) { 51279a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov char c = filter.charAt(i); 51289a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (c >= '0' && c <= '9') { 51299a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov atLeastOneDigit = true; 51309a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } else if (c != '*' && c != '#' && c != '+' && c != 'N' && c != '.' && c != ';' 51319a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov && c != '-' && c != '(' && c != ')' && c != ' ') { 51329a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 51339a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 51349a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 51359a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return atLeastOneDigit; 51369a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 51379a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 51384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 51397a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * Takes components of a name from the query parameters and returns a cursor with those 51407a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * components as well as all missing components. There is no database activity involved 51417a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * in this so the call can be made on the UI thread. 51427a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov */ 51437a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private Cursor completeName(Uri uri, String[] projection) { 51447a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (projection == null) { 51457a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov projection = sDataProjectionMap.getColumnNames(); 51467a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51477a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51487a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ContentValues values = new ContentValues(); 5149f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov DataRowHandlerForStructuredName handler = (DataRowHandlerForStructuredName) 5150f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov getDataRowHandler(StructuredName.CONTENT_ITEM_TYPE); 51517a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51527a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov copyQueryParamsToContentValues(values, uri, 51537a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.DISPLAY_NAME, 51547a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PREFIX, 51557a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.GIVEN_NAME, 51567a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.MIDDLE_NAME, 51577a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.FAMILY_NAME, 51587a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.SUFFIX, 51597a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_NAME, 51607a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_FAMILY_NAME, 51617a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_MIDDLE_NAME, 51627a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_GIVEN_NAME 51637a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ); 51647a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51657a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov handler.fixStructuredNameComponents(values, values); 51667a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51677a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 51687a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov Object[] row = new Object[projection.length]; 51697a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (int i = 0; i < projection.length; i++) { 51707a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov row[i] = values.get(projection[i]); 51717a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51727a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.addRow(row); 51737a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return cursor; 51747a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51757a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51767a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private void copyQueryParamsToContentValues(ContentValues values, Uri uri, String... columns) { 51777a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (String column : columns) { 51787a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String param = uri.getQueryParameter(column); 51797a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (param != null) { 51807a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov values.put(column, param); 51817a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51827a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51837a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51847a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51857a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51867a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov /** 51874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 51884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 51894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 5190b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 5191b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 5192b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 5193b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 5194b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 51954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 51964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 5197b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 5198b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5199b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5200caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 52015e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 52025e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 52035e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 52045e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 52055e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 52065e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 52075e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 52085e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 52095e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 52105e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 52115e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5212caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 5213caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 5214caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 52155f1f4a062ac34d75d2dbf586702cbeb121cf09caDmitri Plotnikov Account[] accounts = accountManager.getAccountsByType(DEFAULT_ACCOUNT_TYPE); 5216caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 5217caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 5218caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5219caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 52206f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 5221caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 52226f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 5223caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5224f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 522573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 522673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov * Returns true if the specified account type is writable. 522773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 522873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov protected boolean isWritableAccount(String accountType) { 5229bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov if (accountType == null) { 5230bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 5231bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 5232bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 523373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov Boolean writable = mAccountWritability.get(accountType); 523473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 523573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 523673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 523773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 5238627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 5239627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 5240627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 5241627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 524273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov accountType.equals(sync.accountType)) { 524373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 524473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 5245627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5246627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5247627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 5248627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 5249627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 525073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 525173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 525273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 525373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 525473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 525573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.put(accountType, writable); 525673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 5257627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5258b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 5259d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 5260f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 5261f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 5262f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5263f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 5264f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5265f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5266f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5267f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5268f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5269f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 5270f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5271f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5272f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5273f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5274f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 5275f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5276f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 5277f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 5278f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5279f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5280f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 5281f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 5282f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 5283f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 5284f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 5285f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5286f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5287f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 5288f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 5289f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 5290f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 5291f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5292f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5293f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5294f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5295f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5296f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 5297f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 5298f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5299f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 5300f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 5301f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 5302f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 5303f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5304f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5305f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5306f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5307f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 5308f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5309f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 5310f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5311f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5312f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5313f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 5314f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 5315f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 5316f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5317f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5318f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5319f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 5320f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 5321f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 5322f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 5323f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 5324f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5325f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5326f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 5327f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 53285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 53290dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov protected boolean isAggregationUpgradeNeeded() { 53300dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 53310dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return false; 53320dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53330dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 53340dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_AGGREGATION_ALGORITHM, "1")); 53350dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return version < PROPERTY_AGGREGATION_ALGORITHM_VERSION; 53360dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53370dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 5338bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void upgradeAggregationAlgorithmInBackground() { 53390dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // This upgrade will affect very few contacts, so it can be performed on the 53400dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // main thread during the initial boot after an OTA 53410dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 53420dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Upgrading aggregation algorithm"); 53430dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int count = 0; 53440dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 53450dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 534649d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 53470dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDb.beginTransaction(); 53480dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Cursor cursor = mDb.query(true, 53490dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Tables.RAW_CONTACTS + " r1 JOIN " + Tables.RAW_CONTACTS + " r2", 53500dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov new String[]{"r1." + RawContacts._ID}, 53510dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov "r1." + RawContacts._ID + "!=r2." + RawContacts._ID + 53520dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.CONTACT_ID + "=r2." + RawContacts.CONTACT_ID + 53530dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_NAME + "=r2." + RawContacts.ACCOUNT_NAME + 53540dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_TYPE + "=r2." + RawContacts.ACCOUNT_TYPE, 53550dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov null, null, null, null, null); 53560dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 53570dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov while (cursor.moveToNext()) { 53580dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long rawContactId = cursor.getLong(0); 53590dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, 53600dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 53610dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov count++; 53620dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53630dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 53640dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov cursor.close(); 53650dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53660dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.aggregateInTransaction(mDb); 53670dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDb.setTransactionSuccessful(); 53680dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDbHelper.setProperty(PROPERTY_AGGREGATION_ALGORITHM, 53690dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov String.valueOf(PROPERTY_AGGREGATION_ALGORITHM_VERSION)); 53700dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 53710dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDb.endTransaction(); 53720dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 53730dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Aggregation algorithm upgraded for " + count 53740dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov + " contacts, in " + (end - start) + "ms"); 53750dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53760dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53779a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 53789a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov /* Visible for testing */ 53799a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean isPhone() { 53809a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (!sIsPhoneInitialized) { 53819a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhone = new TelephonyManager(getContext()).isVoiceCapable(); 53829a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhoneInitialized = true; 53839a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 53849a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return sIsPhone; 53859a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 53864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 5387