ContactsProvider2.java revision ed6bfd922fd84db21de08c1d12e93c501b86560d
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; 2324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoroimport com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns; 2497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 2597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 2697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 2797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 2897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 2997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 3071340347b4862d4b1368a5d69d1667e2245952e4Daisuke Miyakawaimport com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns; 3197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 322f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawaimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 3397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 3497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 3597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 3697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 3797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 3897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 3903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns; 4097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 4197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport com.android.providers.contacts.ContactsDatabaseHelper.StreamItemsColumns; 433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport com.android.providers.contacts.ContactsDatabaseHelper.StreamItemPhotosColumns; 4497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 45ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmannimport com.android.providers.contacts.ContactsDatabaseHelper.Views; 462f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawaimport com.android.providers.contacts.util.DbQueryUtils; 4797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.vcard.VCardComposer; 4897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.vcard.VCardConfig; 4997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Lists; 5097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Maps; 5197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Sets; 5297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 53b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 54caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 555b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 56bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.Notification; 57bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.NotificationManager; 58bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.PendingIntent; 59c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 60568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 61568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 626ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 6335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 6467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 6567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 66627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.IContentService; 67bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.content.Intent; 68568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 70627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 7167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 72f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringertimport android.content.res.AssetFileDescriptor; 733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport android.content.res.Resources; 74e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikovimport android.database.CrossProcessCursor; 754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 76e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikovimport android.database.CursorWindow; 77ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.CursorWrapper; 78ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 7909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor; 8009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor.RowBuilder; 814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 8208ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwoodimport android.database.sqlite.SQLiteDoneException; 834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 85d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.net.Uri.Builder; 86bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Binder; 876ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 88bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Handler; 89bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.HandlerThread; 90bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Message; 91ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringertimport android.os.ParcelFileDescriptor; 92bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Process; 93b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 9415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikovimport android.os.StrictMode; 950dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikovimport android.os.SystemClock; 960e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 973d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 98508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 993de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 100b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 10197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 10297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 10397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 10497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 1056d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Note; 10697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 10797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 10897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 10997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 11097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 111ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 1123de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 1135b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions; 1143de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 11571340347b4862d4b1368a5d69d1667e2245952e4Daisuke Miyakawaimport android.provider.ContactsContract.DataUsageFeedback; 116d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory; 1173de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 118bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.provider.ContactsContract.Intents; 1193de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 12009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 1213de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 122916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 1233de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 12482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 1253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport android.provider.ContactsContract.StreamItems; 1263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport android.provider.ContactsContract.StreamItemPhotos; 12797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.LiveFolders; 12897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.OpenableColumns; 12997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.SyncStateContract; 130a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 1319a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikovimport android.telephony.TelephonyManager; 132a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 133c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 135108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.BufferedWriter; 136d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 137b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 138d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 139d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 140108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.OutputStreamWriter; 141108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.Writer; 14242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.text.SimpleDateFormat; 1437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 14446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawaimport java.util.Arrays; 1455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 14642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.util.Date; 147b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1480e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 150622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 151b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1520e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 153ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1595b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 160caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 161bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 162bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 163bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 16515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_INITIALIZE = 0; 16615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_OPEN_WRITE_ACCESS = 1; 16715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS = 2; 16815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_ACCOUNTS = 3; 16915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_LOCALE = 4; 17015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM = 5; 17105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_SEARCH_INDEX = 6; 17205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_PROVIDER_STATUS = 7; 17305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_DIRECTORIES = 8; 17405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_CHANGE_LOCALE = 9; 175619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Limit for the maximum number of social stream items to store under a raw contact. */ 1803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int MAX_STREAM_ITEMS_PER_RAW_CONTACT = 5; 1813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 1823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 183b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov * Property key for the legacy contact import version. The need for a version 1843d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1853d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1863d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 187b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final String PROPERTY_CONTACTS_IMPORTED = "contacts_imported_v1"; 188b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int PROPERTY_CONTACTS_IMPORT_VERSION = 1; 18951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final String PREF_LOCALE = "locale"; 1903d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1910dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final String PROPERTY_AGGREGATION_ALGORITHM = "aggregation_v2"; 1920dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final int PROPERTY_AGGREGATION_ALGORITHM_VERSION = 2; 1930dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 1940e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1950e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 196a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1982f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 1992f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * Used to insert a column into strequent results, which enables SQL to sort the list using 2002f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * the total times contacted. See also {@link #sStrequentFrequentProjectionMap}. 2012f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 2022f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private static final String TIMES_USED_SORT_COLUMN = "times_used_sort"; 2035e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 204d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 2052f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa + TIMES_USED_SORT_COLUMN + " DESC, " 2069b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 207d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 208d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 209d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 210d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 2116e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 2129b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 2139b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 2149b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 2159b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 2166e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 2179b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 2189b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 2199b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 2209b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 221de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 222de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 2233716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Regex for splitting query strings - we split on any group of non-alphanumeric characters, 2243716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // excluding the @ symbol. 2253716f1447ceb21180d1301790eabd8b9453f486dDave Santoro /* package */ static final String QUERY_TOKENIZER_REGEX = "[^\\w@]+"; 2263716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 227d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 228d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 2295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 2305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 231a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_DATA = 1004; 2325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 2335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 2345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 2355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 236a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_PHOTO = 1009; 237f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 23842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann private static final int CONTACTS_AS_MULTI_VCARD = 1011; 2392149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov private static final int CONTACTS_LOOKUP_DATA = 1012; 2402149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ID_DATA = 1013; 241a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_ENTITIES = 1014; 242a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ENTITIES = 1015; 243a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_LOOKUP_ID_ENTITIES = 1016; 2443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int CONTACTS_ID_STREAM_ITEMS = 1017; 2453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int CONTACTS_LOOKUP_STREAM_ITEMS = 1018; 2463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int CONTACTS_LOOKUP_ID_STREAM_ITEMS = 1019; 2474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 2495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 2505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 25146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 2523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int RAW_CONTACTS_ID_STREAM_ITEMS = 2006; 2534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2546bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2556bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 256ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 25748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 25848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 25948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 26048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 26148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 26248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 26348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 26448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 265a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2666bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 2676bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 268b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 269b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 270b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 27182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 27282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 2731f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 27431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 27531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 276eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 277eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 278ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 279ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 280ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 281ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 28235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 283b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 28435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 285c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 286c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 287c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2881b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2901b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2921b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 29346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 29446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 29509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 29609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 297d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES = 17001; 298d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES_ID = 17002; 299d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3007a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private static final int COMPLETE_NAME = 18000; 3017a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 30224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE = 19000; 30324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_ENTITIES = 19001; 30424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA = 19002; 30524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA_ID = 19003; 30624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_AS_VCARD = 19004; 30724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS = 19005; 30824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID = 19006; 30924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_DATA = 19007; 31024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_ENTITIES = 19008; 31124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 31246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final int DATA_USAGE_FEEDBACK_ID = 20001; 31346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 3143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS = 21000; 3153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_PHOTOS = 21001; 3163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID = 21002; 3173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS = 21003; 3183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS_ID = 21004; 3193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_LIMIT = 21005; 3203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 321dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID = 322dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 323dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME 324dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 325dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE 326dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_TYPE 327dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + " != 0"; 328dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 329dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID = 330dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 331dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 332dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 333dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 334dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND " 335dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + Groups.AUTO_ADD + " != 0"; 336dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 337dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String[] PROJECTION_GROUP_ID 338dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana = new String[]{Tables.GROUPS + "." + Groups._ID}; 339dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 340dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_GROUPMEMBERSHIP_DATA = DataColumns.MIMETYPE_ID + "=? " 341dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.GROUP_ROW_ID + "=? " 342dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.RAW_CONTACT_ID + "=?"; 343dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 344dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_STARRED_FROM_RAW_CONTACTS = 345dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT " + RawContacts.STARRED 346dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?"; 347dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 348e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public class AddressBookCursor extends CursorWrapper implements CrossProcessCursor { 349e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private final CrossProcessCursor mCursor; 350e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private final Bundle mBundle; 351e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 352e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public AddressBookCursor(CrossProcessCursor cursor, String[] titles, int[] counts) { 353e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov super(cursor); 354e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov mCursor = cursor; 355e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov mBundle = new Bundle(); 356e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov mBundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 357e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov mBundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 358e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 359e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 360e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov @Override 361e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public Bundle getExtras() { 362e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov return mBundle; 363e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 364e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 365e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov @Override 366e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public void fillWindow(int pos, CursorWindow window) { 367e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov mCursor.fillWindow(pos, window); 368e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 369e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 370e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov @Override 371e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public CursorWindow getWindow() { 372e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov return mCursor.getWindow(); 373e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 374e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 375e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov @Override 376e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov public boolean onMove(int oldPosition, int newPosition) { 377e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov return mCursor.onMove(oldPosition, newPosition); 378e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 379e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov } 380e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 381d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 382f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 383f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 384f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 38567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 38667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 3876cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 3883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 389f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 390ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 391ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 392d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 39367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 394d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 395ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 397f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov interface RawContactsQuery { 39819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 39919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 40019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 401ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 402ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 403ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 40419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 40519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 40619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 407ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 408ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 40919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 41019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 411c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 412caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 41371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 41471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 41571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 41671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 41771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 41871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 41971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 42071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 42171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 42271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 42371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 42471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 42571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 42671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 427a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 428a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 429a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 430a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 431a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 432a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 433a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 434a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 435a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 436a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 437a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 438a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 439c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Current contacts - those contacted within the last 3 days (in seconds) 440c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_CURRENT = 3 * 24 * 60 * 60; 441c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 442c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Recent contacts - those contacted within the last 30 days (in seconds) 443c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_RECENT = 30 * 24 * 60 * 60; 444c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 445c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov /* 446c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * Sorting order for email address suggestions: first starred, then the rest. 4472262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * second in_visible_group, then the rest. 4482262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * Within the four (starred/unstarred, in_visible_group/not-in_visible_group) groups 4492262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * - three buckets: very recently contacted, then fairly 450c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * recently contacted, then the rest. Within each of the bucket - descending count 45146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * of times contacted (both for data row and for contact row). If all else fails, alphabetical. 45246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * (Super)primary email address is returned before other addresses for the same contact. 453c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov */ 454c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final String EMAIL_FILTER_SORT_ORDER = 4552262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa Contacts.STARRED + " DESC, " 4562262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa + Contacts.IN_VISIBLE_GROUP + " DESC, " 45746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + "(CASE WHEN " + DataUsageStatColumns.LAST_TIME_USED + " < " + EMAIL_FILTER_CURRENT 45846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 0 " 45946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " WHEN " + DataUsageStatColumns.LAST_TIME_USED + " < " + EMAIL_FILTER_RECENT 46046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 1 " 46146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " ELSE 2 END), " 46246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.TIMES_USED + " DESC, " 46346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Contacts.DISPLAY_NAME + ", " 46446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Data.CONTACT_ID + ", " 465c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_SUPER_PRIMARY + " DESC, " 466c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_PRIMARY + " DESC"; 46746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 46846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** Currently same as {@link #EMAIL_FILTER_SORT_ORDER} */ 46946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final String PHONE_FILTER_SORT_ORDER = EMAIL_FILTER_SORT_ORDER; 470c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 471916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 472916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 473916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 474916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 47592ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov NameLookupType.NICKNAME; 476916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 477f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov /** 478f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * If any of these columns are used in a Data projection, there is no point in 479f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * using the DISTINCT keyword, which can negatively affect performance. 480f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov */ 481f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov private static final String[] DISTINCT_DATA_PROHIBITING_COLUMNS = { 482f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data._ID, 483f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.RAW_CONTACT_ID, 484f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.NAME_RAW_CONTACT_ID, 485f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 486f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 487f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.DIRTY, 488f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.NAME_VERIFIED, 489f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SOURCE_ID, 490f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.VERSION, 491f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov }; 492916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 493f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsColumns = ProjectionMap.builder() 494f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CUSTOM_RINGTONE) 495f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME) 496f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_ALTERNATIVE) 497f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_SOURCE) 498f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.IN_VISIBLE_GROUP) 499f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LAST_TIME_CONTACTED) 500f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LOOKUP_KEY) 501f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME) 502f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME_STYLE) 503f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHOTO_ID) 5043d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_URI) 5053d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_THUMBNAIL_URI) 506f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SEND_TO_VOICEMAIL) 507f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_ALTERNATIVE) 508f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_PRIMARY) 509f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.STARRED) 510f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.TIMES_CONTACTED) 511cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 512f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 513f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 514f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsPresenceColumns = ProjectionMap.builder() 515f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 516f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE) 517f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 518f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 519f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 520f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 521f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 522f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 523f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 524f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 525f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 526f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 527f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 528f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 529f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 530f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 531f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSnippetColumns = ProjectionMap.builder() 53203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov .add(SearchSnippetColumns.SNIPPET) 533f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 534f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 535f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactColumns = ProjectionMap.builder() 536f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_NAME) 537f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_TYPE) 538f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DIRTY) 539f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.NAME_VERIFIED) 540f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SOURCE_ID) 541f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.VERSION) 542f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 543f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 544f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactSyncColumns = ProjectionMap.builder() 545f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC1) 546f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC2) 547f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC3) 548f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC4) 549f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 550f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 551f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataColumns = ProjectionMap.builder() 552f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA1) 553f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA2) 554f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA3) 555f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA4) 556f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA5) 557f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA6) 558f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA7) 559f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA8) 560f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA9) 561f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA10) 562f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA11) 563f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA12) 564f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA13) 565f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA14) 566f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA15) 567f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA_VERSION) 568f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_PRIMARY) 569f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_SUPER_PRIMARY) 570f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.MIMETYPE) 571f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RES_PACKAGE) 572f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC1) 573f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC2) 574f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC3) 575f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC4) 576f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(GroupMembership.GROUP_SOURCE_ID) 577f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 578f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 579f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactPresenceColumns = ProjectionMap.builder() 580f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 581f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.PRESENCE) 582f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 583f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.CHAT_CAPABILITY) 584f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 585f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 586f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 587f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 588f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 589f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 590f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 591f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 592f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 593f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 594f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 595f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 596f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataPresenceColumns = ProjectionMap.builder() 597f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.PRESENCE, Tables.PRESENCE + "." + StatusUpdates.PRESENCE) 598f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CHAT_CAPABILITY, Tables.PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 599f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS, StatusUpdatesColumns.CONCRETE_STATUS) 600f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_TIMESTAMP, StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 601f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_RES_PACKAGE, StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 602f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_LABEL, StatusUpdatesColumns.CONCRETE_STATUS_LABEL) 603f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_ICON, StatusUpdatesColumns.CONCRETE_STATUS_ICON) 604f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 605f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 606038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 607f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sCountProjectionMap = ProjectionMap.builder() 608f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(BaseColumns._COUNT, "COUNT(*)") 609f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 610f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 611e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 612f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionMap = ProjectionMap.builder() 613f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts._ID) 614f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 615f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.NAME_RAW_CONTACT_ID) 61624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 617f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 618f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsPresenceColumns) 619f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 620f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 621916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 622f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionWithSnippetMap = ProjectionMap.builder() 623f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 624f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sSnippetColumns) 625f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 626916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6275e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 628f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentStarredProjectionMap = ProjectionMap.builder() 629f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 6302f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 631f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 632f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 633f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder() 634f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 6352f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, "SUM(" + DataUsageStatColumns.CONCRETE_TIMES_USED + ")") 636f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 637f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 638f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 639f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsVCardProjectionMap = ProjectionMap.builder() 640fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen .add(Contacts._ID) 641f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME + " || '.vcf'") 642f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.SIZE, "NULL") 643f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 644f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 645ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 646f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactsProjectionMap = ProjectionMap.builder() 647f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 648f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 649f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 650f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_PRIMARY) 651f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_ALTERNATIVE) 652f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_SOURCE) 653f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME) 654f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME_STYLE) 655f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_PRIMARY) 656f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_ALTERNATIVE) 657f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.TIMES_CONTACTED) 658f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.LAST_TIME_CONTACTED) 659f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CUSTOM_RINGTONE) 660f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SEND_TO_VOICEMAIL) 661f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 662f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.AGGREGATION_MODE) 66324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 664f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 665f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 666f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 667f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 668a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the raw entity view*/ 669f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawEntityProjectionMap = ProjectionMap.builder() 670f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 671f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 672f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.Entity.DATA_ID) 673f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 674f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 67524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 676f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 677f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 678f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 679f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 680f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 681a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the contact entity view*/ 682f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sEntityProjectionMap = ProjectionMap.builder() 683f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity._ID) 684f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.CONTACT_ID) 685f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.RAW_CONTACT_ID) 686f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DATA_ID) 687f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.NAME_RAW_CONTACT_ID) 688f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DELETED) 68924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 690f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 691f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 692f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 693f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 694f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 695f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 696f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 697f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 699f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataProjectionMap = ProjectionMap.builder() 700f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID) 701f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RAW_CONTACT_ID) 702f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CONTACT_ID) 703f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.NAME_RAW_CONTACT_ID) 70424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 705f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 706f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 707f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 708f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 709f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 710f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 711f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 713f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDistinctDataProjectionMap = ProjectionMap.builder() 714f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID, "MIN(" + Data._ID + ")") 715f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 71624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 717f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 718f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 719f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 720f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 721f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 722f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 724f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sPhoneLookupProjectionMap = ProjectionMap.builder() 725f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup._ID, "contacts_view." + Contacts._ID) 726f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LOOKUP_KEY, "contacts_view." + Contacts.LOOKUP_KEY) 727f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.DISPLAY_NAME, "contacts_view." + Contacts.DISPLAY_NAME) 728f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LAST_TIME_CONTACTED, "contacts_view." + Contacts.LAST_TIME_CONTACTED) 729f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TIMES_CONTACTED, "contacts_view." + Contacts.TIMES_CONTACTED) 730f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.STARRED, "contacts_view." + Contacts.STARRED) 731f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.IN_VISIBLE_GROUP, "contacts_view." + Contacts.IN_VISIBLE_GROUP) 732f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.PHOTO_ID, "contacts_view." + Contacts.PHOTO_ID) 7333d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_URI, "contacts_view." + Contacts.PHOTO_URI) 7343d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_THUMBNAIL_URI, "contacts_view." + Contacts.PHOTO_THUMBNAIL_URI) 735f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.CUSTOM_RINGTONE, "contacts_view." + Contacts.CUSTOM_RINGTONE) 736f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.HAS_PHONE_NUMBER, "contacts_view." + Contacts.HAS_PHONE_NUMBER) 737f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.SEND_TO_VOICEMAIL, "contacts_view." + Contacts.SEND_TO_VOICEMAIL) 738f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.NUMBER, Phone.NUMBER) 739f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TYPE, Phone.TYPE) 740f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LABEL, Phone.LABEL) 7412530512f639c4979fd7371c7dd25dd67e8118124Bai Tao .add(PhoneLookup.NORMALIZED_NUMBER, Phone.NORMALIZED_NUMBER) 742f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 743f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 744ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 745f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsProjectionMap = ProjectionMap.builder() 746f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups._ID) 747f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_NAME) 748f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_TYPE) 749f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SOURCE_ID) 750f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DIRTY) 751f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.VERSION) 752f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.RES_PACKAGE) 753f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE) 754f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE_RES) 755f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.GROUP_VISIBLE) 756f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYSTEM_ID) 757f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DELETED) 758f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.NOTES) 759f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SHOULD_SYNC) 760f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.FAVORITES) 761f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.AUTO_ADD) 762c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov .add(Groups.GROUP_IS_READ_ONLY) 763f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC1) 764f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC2) 765f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC3) 766f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC4) 767f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 768f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 769ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 770f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsSummaryProjectionMap = ProjectionMap.builder() 771f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sGroupsProjectionMap) 772f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_COUNT, 773f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 774f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS 775f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP 776f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Clauses.BELONGS_TO_GROUP 777f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ")") 778f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_WITH_PHONES, 779f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 780f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS 781f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP 782f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Clauses.BELONGS_TO_GROUP 783f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ")") 784f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 785f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 786373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 787f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sAggregationExceptionsProjectionMap = ProjectionMap.builder() 788f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id") 789f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.TYPE) 790f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID1) 791f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID2) 792f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 793f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 794eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 795f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSettingsProjectionMap = ProjectionMap.builder() 796f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_NAME) 797f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_TYPE) 798f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_VISIBLE) 799f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.SHOULD_SYNC) 800f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ANY_UNSYNCED, 801f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 802f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ",(SELECT " 803f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "(CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL" 804f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 805f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE MIN(" + Groups.SHOULD_SYNC + ")" 806f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)" 807f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.GROUPS 808f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 809f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_NAME 810f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 811f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0" 812f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 813f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE 0" 814f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)") 815f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_COUNT, 816f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 817f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 818f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 819f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 820f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 821f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 822f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_WITH_PHONES, 823f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 824f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 825f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 826f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Contacts.HAS_PHONE_NUMBER 827f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 828f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 829f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 830f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 831f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 83282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 833f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStatusUpdatesProjectionMap = ProjectionMap.builder() 834f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PresenceColumns.RAW_CONTACT_ID) 835f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.DATA_ID, DataColumns.CONCRETE_ID) 836f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_ACCOUNT) 837f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_HANDLE) 838f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PROTOCOL) 839f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 840f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // properly enforce uniqueness of null values 841f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CUSTOM_PROTOCOL, 842f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL + "=''" 843f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN NULL" 844f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END)") 845f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PRESENCE) 846f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CHAT_CAPABILITY) 847f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS) 848f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_TIMESTAMP) 849f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_RES_PACKAGE) 850f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_ICON) 851f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_LABEL) 852f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 853f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 8543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Contains StreamItems columns */ 8553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemsProjectionMap = ProjectionMap.builder() 8563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems._ID, StreamItemsColumns.CONCRETE_ID) 8573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(RawContacts.CONTACT_ID) 8583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 8593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_PACKAGE) 8603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_ICON) 8613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_LABEL) 8623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TEXT) 8633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TIMESTAMP) 8643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.COMMENTS) 8653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.ACTION) 8663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.ACTION_URI) 8673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 8683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 8693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemPhotosProjectionMap = ProjectionMap.builder() 8703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos._ID, StreamItemPhotosColumns.CONCRETE_ID) 8713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 8723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.STREAM_ITEM_ID) 8733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.SORT_INDEX) 8743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.PICTURE) 8753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.ACTION, StreamItemPhotosColumns.CONCRETE_ACTION) 8763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.ACTION_URI, StreamItemPhotosColumns.CONCRETE_ACTION_URI) 8773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 8783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 8791b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 880f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sLiveFoldersProjectionMap = ProjectionMap.builder() 881f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders._ID, Contacts._ID) 882f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders.NAME, Contacts.DISPLAY_NAME) 883f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 884f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // for contacts without a photo 885f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // .add(LiveFolders.ICON_BITMAP, Photos.DATA) 886f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 887f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 888d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** Contains {@link Directory} columns */ 889f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDirectoryProjectionMap = ProjectionMap.builder() 890f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory._ID) 891f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.PACKAGE_NAME) 892f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.TYPE_RESOURCE_ID) 893f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DISPLAY_NAME) 894f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DIRECTORY_AUTHORITY) 895f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_TYPE) 896f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_NAME) 897f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.EXPORT_SUPPORT) 898778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.SHORTCUT_SUPPORT) 899778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.PHOTO_SUPPORT) 900f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 9017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 9029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 9039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 9049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 9059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 9069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 9079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 9082526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 9092526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 910bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 911bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 912bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 913bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 91451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 91503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_START_MATCH = "["; 91603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_END_MATCH = "]"; 91703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_ELLIPSIS = "..."; 91803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final int DEFAULT_SNIPPET_ARG_MAX_TOKENS = -10; 91903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 9209a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhoneInitialized; 9219a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhone; 9229a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 923f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 9241129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 9251129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 9262526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 9272526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 928f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 929f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 93046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 93146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Stores mapping from type Strings exposed via {@link DataUsageFeedback} to 93246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type integers in {@link DataUsageStatColumns}. 93346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 93446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final Map<String, Integer> sDataUsageTypeMap; 93546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 9364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 9374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 938a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 939d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 940d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 941a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA); 942a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES); 9433653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 9443653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 9452d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 9462d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 947a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO); 9483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/stream_items", 9493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_ID_STREAM_ITEMS); 950c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); 9515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 9525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 9532149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA); 9545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 9552149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", 9562149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov CONTACTS_LOOKUP_ID_DATA); 957a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", 958a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ENTITIES); 959a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", 960a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ID_ENTITIES); 9613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/stream_items", 9623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_STREAM_ITEMS); 9633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/stream_items", 9643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_ID_STREAM_ITEMS); 965f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 96642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 96742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 9685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 969ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 970ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 9715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 9723653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 9735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 9745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 9755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 97646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 9773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items", 9783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann RAW_CONTACTS_ID_STREAM_ITEMS); 97946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 98046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 981b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 9824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 9834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 984ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 98548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 9865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 987ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 9884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 98948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 9901dac83b8fa58944acfd00f44e717a7dddc659d2dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup", EMAILS_LOOKUP); 9915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 9925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 9934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 994ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 99548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 99646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** "*" is in CSV form with data ids ("123,456,789") */ 99746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "data/usagefeedback/*", DATA_USAGE_FEEDBACK_ID); 9981f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 999ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 1000ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 1001ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 1002ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 100335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 1004b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 1005b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 100635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1007a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 1008b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 1009b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 1010b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 1011b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 10124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1013eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 1014eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 101582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 101682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 10171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1018c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 1019c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 1020c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 1021c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 10222d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 1023c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 1024c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 10251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 10261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 10271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 10281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 10291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 10301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 10311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 10321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 103309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 103409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 1035d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1036d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories", DIRECTORIES); 1037d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories/#", DIRECTORIES_ID); 10387a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 10397a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "complete_name", COMPLETE_NAME); 104024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 104124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile", PROFILE); 104224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/entities", PROFILE_ENTITIES); 104324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data", PROFILE_DATA); 104424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data/#", PROFILE_DATA_ID); 104524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/as_vcard", PROFILE_AS_VCARD); 104624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts", PROFILE_RAW_CONTACTS); 104724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#", 104824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID); 104924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/data", 105024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_DATA); 105124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/entity", 105224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_ENTITIES); 105346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 10543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items", STREAM_ITEMS); 10553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/photo", STREAM_ITEMS_PHOTOS); 10563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#", STREAM_ITEMS_ID); 10573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo", STREAM_ITEMS_ID_PHOTOS); 10583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo/#", 10593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann STREAM_ITEMS_ID_PHOTOS_ID); 10603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items_limit", STREAM_ITEMS_LIMIT); 10613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 106246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa HashMap<String, Integer> tmpTypeMap = new HashMap<String, Integer>(); 106346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_CALL, DataUsageStatColumns.USAGE_TYPE_INT_CALL); 106446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_LONG_TEXT, 106546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT); 106646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_SHORT_TEXT, 106746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_SHORT_TEXT); 106846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sDataUsageTypeMap = Collections.unmodifiableMap(tmpTypeMap); 106919a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 107019a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 1071d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static class DirectoryInfo { 1072d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String authority; 1073d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountName; 1074d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountType; 1075d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 1076d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1077d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 1078d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Cached information about contact directories. 1079d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 10804458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private HashMap<String, DirectoryInfo> mDirectoryCache = new HashMap<String, DirectoryInfo>(); 10814458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private boolean mDirectoryCacheValid = false; 1082d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 10833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1084ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 1085ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1086ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1087e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov public static class GroupIdCacheEntry { 1088ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1089ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 1090ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1091ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1092ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1093a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1094e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1095e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1096e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // is a list of groups with this group id. 1097e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1098e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov 109924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 110024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Cached information about the contact ID and raw contact IDs that make up the user's 110124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * profile entry. 110224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro */ 110324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static class ProfileIdCache { 110424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro boolean inited; 110524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long profileContactId; 110624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Set<Long> profileRawContactIds = Sets.newHashSet(); 110724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Set<Long> profileDataIds = Sets.newHashSet(); 110824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 110924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 111024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Initializes the cache of profile contact and raw contact IDs. Does nothing if 111124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * the cache is already initialized (unless forceRefresh is set to true). 111224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * @param db The contacts database. 111324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * @param forceRefresh Whether to force re-initialization of the cache. 111424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro */ 111524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private void init(SQLiteDatabase db, boolean forceRefresh) { 111624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!inited || forceRefresh) { 111724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileContactId = 0; 111824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileRawContactIds.clear(); 111924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileDataIds.clear(); 112024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Cursor c = db.rawQuery("SELECT " + 112124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro RawContactsColumns.CONCRETE_CONTACT_ID + "," + 112224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro RawContactsColumns.CONCRETE_ID + "," + 112324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro DataColumns.CONCRETE_ID + 112424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro " FROM " + Tables.RAW_CONTACTS + " JOIN " + Tables.ACCOUNTS + " ON " + 112524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro RawContactsColumns.CONCRETE_ID + "=" + 112624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro AccountsColumns.PROFILE_RAW_CONTACT_ID + 112724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro " JOIN " + Tables.DATA + " ON " + 112824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro RawContactsColumns.CONCRETE_ID + "=" + DataColumns.CONCRETE_RAW_CONTACT_ID, 112924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro null); 113024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro try { 113124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro while (c.moveToNext()) { 113224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (profileContactId == 0) { 113324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileContactId = c.getLong(0); 113424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 113524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileRawContactIds.add(c.getLong(1)); 113624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileDataIds.add(c.getLong(2)); 113724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 113824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } finally { 113924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro c.close(); 114024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 114124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 114224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 114324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 114424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 114524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private ProfileIdCache mProfileIdCache; 114624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 11473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Limit for the maximum byte size of social stream item photos (loaded from config.xml). */ 11483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int mMaxStreamItemPhotoSizeBytes; 11493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 11503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 1151b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 115231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 11534097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1154f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1155315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1156622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1157622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 115872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private ContactDirectoryManager mContactDirectoryManager; 1159622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1160f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1161a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1162d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1163f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private SearchIndexManager mSearchIndexManager; 1164a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 116520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 116673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 116720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 116809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 11693826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private boolean mProviderStatusUpdateNeeded; 117009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 117115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mReadAccessLatch; 117215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mWriteAccessLatch; 117315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private boolean mAccountUpdateListenerRegistered; 1174bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private boolean mOkToOpenAccess = true; 117573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1176d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private TransactionContext mTransactionContext = new TransactionContext(); 1177de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 11781a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 11791a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 118081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 118181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 11824cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 11833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private int mContactsAccountCount; 1184d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1185bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private HandlerThread mBackgroundThread; 1186bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private Handler mBackgroundHandler; 1187bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 11884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 11894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1190de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1191ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1192ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1193ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1194ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1195ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1196ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1197ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 119835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1199ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 120015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov StrictMode.setThreadPolicy( 120115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); 120215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 12033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Resources resources = getContext().getResources(); 12043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mMaxStreamItemPhotoSizeBytes = resources.getInteger( 12053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann R.integer.config_stream_item_photo_max_bytes); 12063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 120724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mProfileIdCache = new ProfileIdCache(); 1208b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 120972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager = new ContactDirectoryManager(this); 1210a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 121165ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 1212bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // The provider is closed for business until fully initialized 121315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = new CountDownLatch(1); 121415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = new CountDownLatch(1); 121572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1216bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread = new HandlerThread("ContactsProviderWorker", 1217bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Process.THREAD_PRIORITY_BACKGROUND); 1218bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread.start(); 1219bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { 1220bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 1221bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void handleMessage(Message msg) { 1222bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov performBackgroundTask(msg.what, msg.obj); 1223bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1224bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov }; 12252a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 122615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_INITIALIZE); 1227bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1228bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 1229bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_LOCALE); 1230bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM); 123105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_SEARCH_INDEX); 1232bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_PROVIDER_STATUS); 123315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_OPEN_WRITE_ACCESS); 12343826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 123549d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov return true; 12364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 12374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1238767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 123951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 124051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 124104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 124215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 124315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 12444cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 124504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov mNameSplitter = mDbHelper.createNameSplitter(); 12464cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 12474cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 124851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mCommonNicknameCache = new CommonNicknameCache(mDbHelper.getReadableDatabase()); 1249cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 12505b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper, 125115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 12525b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1253f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSearchIndexManager = new SearchIndexManager(this); 12545b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 1255bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 1256bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1257bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, 12586d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForEmail(context, mDbHelper, mContactAggregator)); 1259bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 12606d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForIm(context, mDbHelper, mContactAggregator)); 1261bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, 12626d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForOrganization(context, mDbHelper, mContactAggregator)); 1263bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, 12646d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForPhoneNumber(context, mDbHelper, mContactAggregator)); 1265bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, 12666d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForNickname(context, mDbHelper, mContactAggregator)); 1267bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 12686d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForStructuredName(context, mDbHelper, mContactAggregator, 1269bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mNameSplitter, mNameLookupBuilder)); 1270bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 12716d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForStructuredPostal(context, mDbHelper, mContactAggregator, 1272bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mPostalSplitter)); 1273bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, 12746d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForGroupMembership(context, mDbHelper, mContactAggregator, 1275bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mGroupIdCache)); 1276bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, 12776d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForPhoto(context, mDbHelper, mContactAggregator)); 12786d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov mDataRowHandlers.put(Note.CONTENT_ITEM_TYPE, 12796d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov new DataRowHandlerForNote(context, mDbHelper, mContactAggregator)); 1280bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1281bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1282bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /** 1283bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Visible for testing. 1284bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov */ 1285bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 1286bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return new PhotoPriorityResolver(context); 1287bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1288bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1289bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task) { 1290bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendEmptyMessage(task); 1291bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1292bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1293bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task, Object arg) { 1294bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(task, arg)); 1295bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1296bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1297bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void performBackgroundTask(int task, Object arg) { 1298bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov switch (task) { 129915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_INITIALIZE: { 130015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov initForDefaultLocale(); 130115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch.countDown(); 130215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = null; 130315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov break; 130415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 130515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 130615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_OPEN_WRITE_ACCESS: { 1307bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (mOkToOpenAccess) { 130815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch.countDown(); 130915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = null; 1310bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1311bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1312bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1313bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1314bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS: { 1315bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1316bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov importLegacyContactsInBackground(); 1317bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1318bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1319bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1320bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1321bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_ACCOUNTS: { 132215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 132315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (!mAccountUpdateListenerRegistered) { 132415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov AccountManager.get(context).addOnAccountsUpdatedListener(this, null, false); 132515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mAccountUpdateListenerRegistered = true; 132615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 132715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 132815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Account[] accounts = AccountManager.get(context).getAccounts(); 1329bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean accountsChanged = updateAccountsInBackground(accounts); 1330bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateContactsAccountCount(accounts); 1331bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateDirectoriesInBackground(accountsChanged); 1332bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1333bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1334bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1335bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_LOCALE: { 1336bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateLocaleInBackground(); 1337bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1338bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1339bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1340fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov case BACKGROUND_TASK_CHANGE_LOCALE: { 1341fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov changeLocaleInBackground(); 1342fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov break; 1343fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1344fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1345bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM: { 1346bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isAggregationUpgradeNeeded()) { 1347bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov upgradeAggregationAlgorithmInBackground(); 1348bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1349bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1350bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1351bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 135205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_SEARCH_INDEX: { 135305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov updateSearchIndexInBackground(); 135405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov break; 135505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 135605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1357bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_PROVIDER_STATUS: { 1358bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateProviderStatus(); 1359bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1360bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1361bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1362bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_DIRECTORIES: { 1363bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (arg != null) { 1364bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.onPackageChanged((String) arg); 1365bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1366bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1367bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1368bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 13694cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 13704cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 137153fac8f99f3884c372c907a76766d27fa9e1d95fDmitri Plotnikov public void onLocaleChanged() { 13723826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 13733826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 13744f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov return; 13754f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov } 13764f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 1377fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_CHANGE_LOCALE); 13784cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 137951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 138051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 138151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 138251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 138351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 138451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 138551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 138651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 1387bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateLocaleInBackground() { 1388f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 1389f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 1390f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 1391f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 1392f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 1393f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 139451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 139551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 139651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 139751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 139851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 139951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 140051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 140151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 140251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 1403bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDbHelper.setLocale(this, currentLocale); 1404bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).apply(); 1405bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov setProviderStatus(providerStatus); 1406bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 140751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1408fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov /** 1409fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov * Reinitializes the provider for a new locale. 1410fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov */ 1411fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private void changeLocaleInBackground() { 1412fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Re-initializing the provider without stopping it. 1413fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Locking the database will prevent inserts/updates/deletes from 1414fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // running at the same time, but queries may still be running 1415fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // on other threads. Those queries may return inconsistent results. 1416fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getWritableDatabase(); 1417fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.beginTransaction(); 1418fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov try { 1419fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov initForDefaultLocale(); 1420fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.setTransactionSuccessful(); 1421fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } finally { 1422fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.endTransaction(); 1423fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1424fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1425fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov updateLocaleInBackground(); 1426fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1427fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 142805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov protected void updateSearchIndexInBackground() { 142905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mSearchIndexManager.updateIndex(); 143005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 143105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1432bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateDirectoriesInBackground(boolean rescan) { 1433bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanAllPackages(rescan); 143451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 143551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 14363826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateProviderStatus() { 14373826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 14383826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 14393826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return; 14403826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 14413826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 14423826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mContactsAccountCount == 0 144349d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov && DatabaseUtils.queryNumEntries(mDbHelper.getReadableDatabase(), 144449d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Tables.CONTACTS, null) == 0) { 14453826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 14463826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } else { 14473826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 14483826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 14493826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 14503826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 145131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1452de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1453b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1454b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 145531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 145631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1457013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1458013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1459013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1460013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 14615df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov /* package */ NameLookupBuilder getNameLookupBuilder() { 14625df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov return mNameLookupBuilder; 14635df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov } 14645df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov 14655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 1466ed78fd6df5e9f3a2d572162e5d374d1f4a625bddDmitri Plotnikov public ContactDirectoryManager getContactDirectoryManagerForTest() { 146772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return mContactDirectoryManager; 146872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 146972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 147072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 14715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 14725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 14735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 14745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 14753d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 1476b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 1477b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 14783d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 14793d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1480568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1481568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1482568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1483568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1484568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1485bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Imports legacy contacts as a background task. 1486568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1487bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private void importLegacyContactsInBackground() { 1488bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 1489bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 1490568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1491bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 1492bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDbHelper.setLocale(this, mCurrentLocale); 1493bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 1494568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1495bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1496bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (importLegacyContacts(importer)) { 1497bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportSuccess(); 1498bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } else { 1499bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportFailure(); 1500bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1501568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1502568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1503bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1504bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 1505bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1506bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 1507bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1508bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 1509bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 1510bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1511b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 1512b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDbHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 1513b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 1514bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 1515bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 1516bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1517bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1518bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1519bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 1520bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1521bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 1522bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 1523bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1524bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 1525bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1526bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 1527bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 1528bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 1529bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 1530bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 1531bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 1532bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 1533bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 1534bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 1535bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1536bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 1537bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1538bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 1539bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 1540bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1541bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // Do not let any database changes until this issue is resolved. 1542bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mOkToOpenAccess = false; 15433d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 15443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 15453d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1546568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 15470e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 15483d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 15493d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 1550bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 1551bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1552bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1553bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 1554bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 1555bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 15563d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 15573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 15583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1559bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 1560bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 15613d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 15623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1563a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1564a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1565a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1566a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1567b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 15683826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS; 1569a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1570a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1571568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 157215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov * During intialization, this content provider will 1573568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1574568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1575568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1576568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1577568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 157815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private void waitForAccess(CountDownLatch latch) { 157915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (latch == null) { 158015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 158115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 158215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 158315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov while (true) { 158415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov try { 158515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov latch.await(); 158615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 158715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } catch (InterruptedException e) { 158815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Thread.currentThread().interrupt(); 1589ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1590568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1591568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1592568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1593568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1594568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 159515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1596568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 1597568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1598568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1599568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1600568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 160115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (mWriteAccessLatch != null) { 1602bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 1603bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 1604bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 1605bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 1606bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (match == PROVIDER_STATUS) { 1607bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 1608bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 1609bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1610bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 1611bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 1612bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 1613bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1614bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1615bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 161615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1617568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 1618568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1619568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1620568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1621568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 162215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1623568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 1624568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1625568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1626568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1627568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1628568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 162915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 1630568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 1631568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1632568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 16334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 16347b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov public int bulkInsert(Uri uri, ContentValues[] values) { 16357b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov waitForAccess(mWriteAccessLatch); 16367b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov return super.bulkInsert(uri, values); 16377b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov } 16387b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov 16397b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov @Override 1640285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 1641bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1642b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 1643b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1644285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 16451ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 1646d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.clear(); 1647b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1648b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1649285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1650285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1651285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 16521129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 1653bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1654b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 1655b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1656285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 1657b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 1658bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mContactAggregator.aggregateInTransaction(mTransactionContext, mDb); 16591a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 16601a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 1661b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 16621a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 16633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 1664bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 1665bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 16663826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatusUpdateNeeded) { 16673826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 16683826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = false; 16693826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 1670b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1671b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1672bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov private void updateSearchIndexInTransaction() { 1673bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov Set<Long> staleContacts = mTransactionContext.getStaleSearchIndexContactIds(); 1674bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov Set<Long> staleRawContacts = mTransactionContext.getStaleSearchIndexRawContactIds(); 1675bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov if (!staleContacts.isEmpty() || !staleRawContacts.isEmpty()) { 1676bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mSearchIndexManager.updateIndexForRawContacts(staleContacts, staleRawContacts); 1677bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mTransactionContext.clearSearchIndexUpdates(); 1678bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 1679bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 1680bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 1681b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 1682bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 1683b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 1684b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 16851129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 168624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Determine whether we need to refresh the profile ID cache. 168724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro boolean profileCacheRefreshNeeded = false; 168824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 1689d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov for (long rawContactId : mTransactionContext.getInsertedRawContactIds()) { 16908ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov mDbHelper.updateRawContactDisplayName(mDb, rawContactId); 1691bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mContactAggregator.onRawContactInsert(mTransactionContext, mDb, rawContactId); 1692285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1693b5a4add17815167d20a90645779df34cdf45280dFred Quintana 169424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Map<Long, Account> insertedProfileRawContactAccountMap = 169524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mTransactionContext.getInsertedProfileRawContactIds(); 169624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!insertedProfileRawContactAccountMap.isEmpty()) { 169724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro for (long profileRawContactId : insertedProfileRawContactAccountMap.keySet()) { 169824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mDbHelper.updateRawContactDisplayName(mDb, profileRawContactId); 169924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mContactAggregator.onProfileRawContactInsert(mTransactionContext, mDb, 170024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileRawContactId, 170124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro insertedProfileRawContactAccountMap.get(profileRawContactId)); 170224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 170324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileCacheRefreshNeeded = true; 170424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 170524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 1706d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov Set<Long> dirtyRawContacts = mTransactionContext.getDirtyRawContactIds(); 1707d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!dirtyRawContacts.isEmpty()) { 1708a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 1709a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 1710d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, dirtyRawContacts); 1711a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 1712a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 171324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 171424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileCacheRefreshNeeded = profileCacheRefreshNeeded || 171524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro !Collections.disjoint(mProfileIdCache.profileRawContactIds, dirtyRawContacts); 1716a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 1717a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1718d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov Set<Long> updatedRawContacts = mTransactionContext.getUpdatedRawContactIds(); 1719d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!updatedRawContacts.isEmpty()) { 1720a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 1721a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 1722d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, updatedRawContacts); 1723a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 1724a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 172524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 172624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileCacheRefreshNeeded = profileCacheRefreshNeeded || 172724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro !Collections.disjoint(mProfileIdCache.profileRawContactIds, updatedRawContacts); 1728b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1729b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1730d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov for (Map.Entry<Long, Object> entry : mTransactionContext.getUpdatedSyncStates()) { 1731b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 17329d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana if (mDbHelper.getSyncState().update(mDb, id, entry.getValue()) <= 0) { 17339d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 17349d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 17359d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 1736b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1737b5a4add17815167d20a90645779df34cdf45280dFred Quintana 173824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (profileCacheRefreshNeeded) { 173924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Force the profile ID cache to refresh. 174024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mProfileIdCache.init(mDb, true); 174124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 174224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 1743d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.clear(); 1744b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1745b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1746a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 1747a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 1748a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 1749a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 1750d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private void appendIds(StringBuilder sb, Set<Long> ids) { 1751b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 1752a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 1753b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1754a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1755a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 1756285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1757285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 175824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 175924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Checks whether the given contact ID represents the user's personal profile - if it is, calls 176024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * a permission check (for writing the profile if forWrite is true, for reading the profile 176124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * otherwise). If the contact ID is not the user's profile, no check is executed. 176224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * @param contactId The contact ID to be checked. 176324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * @param forWrite Whether the caller is attempting to do a write (vs. read) operation. 176424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro */ 176524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private void enforceProfilePermissionForContact(long contactId, boolean forWrite) { 176624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mProfileIdCache.init(mDb, false); 176724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (mProfileIdCache.profileContactId == contactId) { 176824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(forWrite); 176924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 177024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 177124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 177224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 177324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Checks whether the given raw contact ID is a member of the user's personal profile - if it 177424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * is, calls a permission check (for writing the profile if forWrite is true, for reading the 177524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * profile otherwise). If the raw contact ID is not in the user's profile, no check is 177624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * executed. 177724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * @param rawContactId The raw contact ID to be checked. 177824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * @param forWrite Whether the caller is attempting to do a write (vs. read) operation. 177924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro */ 178024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private void enforceProfilePermissionForRawContact(long rawContactId, boolean forWrite) { 178124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mProfileIdCache.init(mDb, false); 178224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (mProfileIdCache.profileRawContactIds.contains(rawContactId)) { 178324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(forWrite); 178424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 178524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 178624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 178724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 178824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Checks whether the given data ID is a member of the user's personal profile - if it is, 178924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * calls a permission check (for writing the profile if forWrite is true, for reading the 179024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * profile otherwise). If the data ID is not in the user's profile, no check is executed. 179124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * @param dataId The data ID to be checked. 179224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * @param forWrite Whether the caller is attempting to do a write (vs. read) operation. 179324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro */ 179424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private void enforceProfilePermissionForData(long dataId, boolean forWrite) { 179524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mProfileIdCache.init(mDb, false); 179624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (mProfileIdCache.profileDataIds.contains(dataId)) { 179724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(forWrite); 179824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 179924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 180024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 180124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 180224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Performs a permission check for WRITE_PROFILE or READ_PROFILE (depending on the parameter). 180324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * If the permission check fails, this will throw a SecurityException. 180424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * @param forWrite Whether the caller is attempting to do a write (vs. read) operation. 180524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro */ 180624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private void enforceProfilePermission(boolean forWrite) { 180724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String profilePermission = forWrite 180824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro ? "android.permission.WRITE_PROFILE" 180924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro : "android.permission.READ_PROFILE"; 181024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro getContext().enforceCallingOrSelfPermission(profilePermission, null); 181124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 181224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 1813285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 1814cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 181581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 181681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 181781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 181881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 181981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 182081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 182181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 1822cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 1823568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 182451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 18253826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != status) { 18263826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = status; 18273826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov getContext().getContentResolver().notifyChange(ProviderStatus.CONTENT_URI, null, false); 18283826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 182951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 183051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1831f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public DataRowHandler getDataRowHandler(final String mimeType) { 18323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 18333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 18346d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov handler = new DataRowHandlerForCustomMimetype( 18356d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov getContext(), mDbHelper, mContactAggregator, mimeType); 18363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 18373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 18383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 18393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 18403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 18414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 1842de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 1843bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 18441129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 1845b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 1846f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1847f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 1848f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 1849f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1850a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 1851a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 185235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1853a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 185435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 1855b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 185635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 185735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1858d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1859d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 18606bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 18616bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 18626bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 186324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 186424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro throw new UnsupportedOperationException( 186524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "The profile contact is created automatically"); 186624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 186724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 18685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 186924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro id = insertRawContact(uri, values, callerIsSyncAdapter, false); 1870f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1871a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1872a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1873a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 18745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 18755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 1876f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1877f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1878a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1879a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1880a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 18813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 18823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItems.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 18833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 18843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 18853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 18863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 18873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 188824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: { 188924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(true); 189024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro id = insertRawContact(uri, values, callerIsSyncAdapter, true); 189124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mSyncToNetwork |= !callerIsSyncAdapter; 189224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 189324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 189424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 1895a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 1896f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 1897f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1898a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1899a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1900a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1901ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1902f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 1903f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 1904ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1905ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1906ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1907eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 19085aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 190943880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 1910eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 1911eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 1912eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 191382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 191482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 19151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 19161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 19171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 19183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 19193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 19203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 19213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 19223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 19233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 19243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 19253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 19263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 19273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 19283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 19293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 19303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 19313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItemPhotos.STREAM_ITEM_ID, uri.getPathSegments().get(1)); 19323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 19333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 19343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 19353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 19363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 1937a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 193881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 1939f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 1940a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1941a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 19427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 19437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 19447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 19457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1946de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 1947a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1948a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1949a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1950e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 1951e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 1952e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 1953e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 1954e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 1955e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 1956e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 1957e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 1958e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 1959e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 1960e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 1961e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 1962e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 19637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 1964e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 1965f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 1966f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 1967e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 1968f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1969f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 1970f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 1971e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 1972e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 1973e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1974e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 1975e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 1976fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 1977fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 1978e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 1979e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1980e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 1981e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 1982e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 1983e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 1984e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1985e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 1986e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 1987e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 1988e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 1989e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 1990fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 1991fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 1992e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 1993e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 1994e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 1995f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 1996f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 1997e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 1998f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 1999f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2000e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2001e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2002f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2003f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2004e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2005f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2006f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2007f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2008f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2009035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2010f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2011e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 20127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 20137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 20147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2015d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 20166bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 20176bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 20186bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 20196bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2020d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2021de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 20226bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 20236bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 20246bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 202524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Inserts an item in the raw contacts table 2026a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2027f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2028f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2029dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param callerIsSyncAdapter 203024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * @param forProfile Whether this raw contact is being inserted into the user's profile. 2031a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2032a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 203324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private long insertRawContact(Uri uri, ContentValues values, boolean callerIsSyncAdapter, 203424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro boolean forProfile) { 2035f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2036f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2037f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2038f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2039e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 20407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 20413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 20423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2043f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 20443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 20453d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2046f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 2047f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 204824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (forProfile) { 204924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Profile raw contacts should never be aggregated by the aggregator; they are always 205024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // aggregated under a single profile contact. 205124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro aggregationMode = RawContacts.AGGREGATION_MODE_DISABLED; 205224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } else if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 2053f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 2054f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2055f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId, aggregationMode); 2056285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 205724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (forProfile) { 205824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Trigger creation of the user profile Contact (or association with the existing one) 205924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // at the end of the transaction. 206024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mTransactionContext.profileRawContactInserted(rawContactId, account); 206124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } else { 206224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Trigger creation of a Contact based on this RawContact at the end of transaction 206324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mTransactionContext.rawContactInserted(rawContactId, account); 206424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 2065f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2066dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 2067dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 2068dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long starred = values.getAsLong(RawContacts.STARRED); 2069dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (starred != null && starred != 0) { 2070dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred != 0); 2071dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2072dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2073dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 20743826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 2075023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2076a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2077a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2078dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void addAutoAddMembership(long rawContactId) { 2079dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID, 2080dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2081dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2082dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2083dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2084dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2085dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2086dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private Long findGroupByRawContactId(String selection, long rawContactId) { 2087dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.GROUPS + "," + Tables.RAW_CONTACTS, PROJECTION_GROUP_ID, 2088dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, 2089dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}, 2090dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana null /* groupBy */, null /* having */, null /* orderBy */); 2091dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 2092dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 2093dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return c.getLong(0); 2094dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2095dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return null; 2096dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2097dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 2098dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2099dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2100dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2101dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateFavoritesMembership(long rawContactId, boolean isStarred) { 2102dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID, 2103dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2104dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2105dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (isStarred) { 2106dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2107dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2108dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana deleteDataGroupMembership(rawContactId, groupId); 2109dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2110dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2111dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2112dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2113dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void insertDataGroupMembership(long rawContactId, long groupId) { 2114dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues groupMembershipValues = new ContentValues(); 2115dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.GROUP_ROW_ID, groupId); 2116dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 2117dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(DataColumns.MIMETYPE_ID, 2118dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDbHelper.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 2119dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.insert(Tables.DATA, null, groupMembershipValues); 2120dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2121dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2122dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void deleteDataGroupMembership(long rawContactId, long groupId) { 2123dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final String[] selectionArgs = { 2124dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(mDbHelper.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)), 2125dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(groupId), 2126dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(rawContactId)}; 2127dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs); 2128dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2129dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2130a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2131a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2132a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2133a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2134a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2135a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2136f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2137a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2138de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2139de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 214067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2141de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 214220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 214324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // If the data being inserted belongs to the user's profile entry, check for the 214424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // WRITE_PROFILE permission before proceeding. 214524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForRawContact(rawContactId, true); 214624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 2147de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2148de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2149de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2150b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2151de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2152de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2153508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2154de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2155de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2156de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2157de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2158de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 21594097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2160b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2161de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2162a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2163a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2164d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov id = rowHandler.insert(mDb, mTransactionContext, rawContactId, mValues); 2165f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2166d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.markRawContactDirty(rawContactId); 2167a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2168d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.rawContactUpdated(rawContactId); 2169a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 21704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 21714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 21723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 21733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_items table. The account is checked against the 21743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account in the raw contact for which the stream item is being inserted. If the 21753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * new stream item results in more stream items under this raw contact than the limit, 21763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest one will be deleted (note that if the stream item inserted was the 21773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * oldest, it will be immediately deleted, and this will return 0). 21783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 21793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 21803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 21813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return the stream item _ID of the newly created row, or 0 if it was not created 21823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 21833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItem(Uri uri, ContentValues values) { 21843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 21853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 21863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 21873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 21883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = mValues.getAsLong(StreamItems.RAW_CONTACT_ID); 21893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 21903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If the data being inserted belongs to the user's profile entry, check for the 21913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // WRITE_PROFILE permission before proceeding. 21923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceProfilePermissionForRawContact(rawContactId, true); 21933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 21943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 21953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 21963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 21973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 21983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Insert the new stream item. 21993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = mDb.insert(Tables.STREAM_ITEMS, null, values); 22003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 22013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check to see if we're over the limit for stream items under this raw contact. 22023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // It's possible that the inserted stream item is older than the the existing 22033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // ones, in which case it may be deleted immediately (resetting the ID to 0). 22043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = cleanUpOldStreamItems(rawContactId, id); 22053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 22063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 22073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 22083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 22093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 22103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_item_photos table. The account is checked against 22113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the account in the raw contact that owns the stream item being modified. 22123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 22133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 22143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 22153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return the stream item photo _ID of the newly created row 22163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 22173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItemPhoto(Uri uri, ContentValues values) { 22183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 22193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 22203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 22213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 22223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = mValues.getAsLong(StreamItemPhotos.STREAM_ITEM_ID); 22233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemId != 0) { 22243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = lookupRawContactIdForStreamId(streamItemId); 22253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 22263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If the data being inserted belongs to the user's profile entry, check for the 22273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // WRITE_PROFILE permission before proceeding. 22283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceProfilePermissionForRawContact(rawContactId, true); 22293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 22303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 22313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 22323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 22333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 22343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Make certain that the photo doesn't exceed our maximum byte size. 22353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann byte[] photoBytes = values.getAsByteArray(StreamItemPhotos.PICTURE); 22363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Log.i(TAG, "Inserting " + photoBytes.length + "-byte photo (max allowed " + 22373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mMaxStreamItemPhotoSizeBytes + " bytes)"); 22383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (photoBytes.length > mMaxStreamItemPhotoSizeBytes) { 22393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann throw new IllegalArgumentException("Stream item photos cannot be more than " + 22403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mMaxStreamItemPhotoSizeBytes + " bytes (received picture with " + 22413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann photoBytes.length + " bytes)"); 22423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 22433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 22443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = mDb.insert(Tables.STREAM_ITEM_PHOTOS, null, values); 22453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 22463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 22473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 22483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 22493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 22503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Looks up the raw contact ID that owns the specified stream item. 22513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param streamItemId The ID of the stream item. 22523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The associated raw contact ID, or -1 if no such stream item exists. 22533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 22543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long lookupRawContactIdForStreamId(long streamItemId) { 22553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = -1; 22563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c = mDb.query(Tables.STREAM_ITEMS, new String[]{StreamItems.RAW_CONTACT_ID}, 22573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems._ID + "=?", new String[]{String.valueOf(streamItemId)}, 22583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 22593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 22603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c.moveToFirst()) { 22613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann rawContactId = c.getLong(0); 22623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 22633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 22643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 22653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 22663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return rawContactId; 22673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 22683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 22693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 22703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given raw contact ID is owned by the given account. 22713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account is null, this will return true iff the raw contact 22723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * is also associated with the "null" account. 22733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 22743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account does not match, this will throw a security exception. 22753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 22763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to check for. 22773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 22783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void enforceModifyingAccount(Account account, long rawContactId) { 22793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String accountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 22803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + "=? AND " 22813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + "=?"; 22823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String noAccountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 22833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL AND " 22843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL"; 22853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c; 22863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (account != null) { 22873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContactsColumns.CONCRETE_ID}, 22883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann accountSelection, 22893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(rawContactId), mAccount.name, mAccount.type}, 22903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 22913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 22923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContactsColumns.CONCRETE_ID}, 22933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann noAccountSelection, new String[]{String.valueOf(rawContactId)}, 22943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 22953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 22963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 22973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if(c.getCount() == 0) { 22983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann throw new SecurityException("Caller account does not match raw contact ID " 22993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + rawContactId); 23003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 23023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 23033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 23063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 23073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream items matches up with the given 23083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 23093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 23103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 23113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 23123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 23133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item IDs that would be included in this selection. 23143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 23153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItems(Account account, String selection, 23163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 23173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = Lists.newArrayList(); 23183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 23193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 23203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c = qb.query(mDb, 23213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{StreamItems._ID, StreamItems.RAW_CONTACT_ID}, 23223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 23233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 23243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 23253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemIds.add(c.getLong(0)); 23263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 23273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 23283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 23293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 23313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 23323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds; 23343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 23363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 23373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream item photos matches up with the given 23383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 23393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 23403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 23413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 23423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 23433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item photo IDs that would be included in this selection. 23443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 23453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItemPhotos(Account account, String selection, 23463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 23473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemPhotoIds = Lists.newArrayList(); 23483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 23493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 23503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c = qb.query(mDb, new String[]{StreamItemPhotos._ID, StreamItems.RAW_CONTACT_ID}, 23513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 23523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 23533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 23543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemPhotoIds.add(c.getLong(0)); 23553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 23563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 23573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 23583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 23603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 23613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemPhotoIds; 23633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 23653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 23663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Queries the database for stream items under the given raw contact. If there are 23673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * more entries than {@link ContactsProvider2#MAX_STREAM_ITEMS_PER_RAW_CONTACT}, 23683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest entries (as determined by timestamp) will be deleted. 23693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to examine for stream items. 23703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param insertedStreamItemId The ID of the stream item that was just inserted, 23713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * prompting this cleanup. Callers may pass 0 if no insertion prompted the 23723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * cleanup. 23733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The ID of the inserted stream item if it still exists after cleanup; 23743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 0 otherwise. 23753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 23763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long cleanUpOldStreamItems(long rawContactId, long insertedStreamItemId) { 23773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long postCleanupInsertedStreamId = insertedStreamItemId; 23783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c = mDb.query(Tables.STREAM_ITEMS, new String[]{StreamItems._ID}, 23793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 23803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, StreamItems.TIMESTAMP + " DESC, " + StreamItems._ID + " DESC"); 23813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 23823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int streamItemCount = c.getCount(); 23833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemCount <= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 23843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Still under the limit - nothing to clean up! 23853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return insertedStreamItemId; 23863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 23873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToLast(); 23883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.getPosition() >= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 23893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = c.getLong(0); 23903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (insertedStreamItemId == streamItemId) { 23913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // The stream item just inserted is being deleted. 23923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann postCleanupInsertedStreamId = 0; 23933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(c.getLong(0)); 23953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToPrevious(); 23963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 23983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 23993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 24003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return postCleanupInsertedStreamId; 24023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 2404ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 24058ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov mDbHelper.updateRawContactDisplayName(db, rawContactId); 2406d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2407d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 24089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 240920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 241020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2411f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 241220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 241320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2414de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2415de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 2416f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, 2417f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 2418de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2419de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 2420f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID); 242124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 242224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Check for write profile permission if the data belongs to the profile. 242324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForRawContact(rawContactId, true); 242424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 2425f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 2426a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2427d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov count += rowHandler.delete(mDb, mTransactionContext, c); 2428f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2429d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.markRawContactDirty(rawContactId); 243088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 243120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 243220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2433de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 243420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 243520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 243620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 243720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 243820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 243988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 244088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 244188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 244220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2443f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 244488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 244588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 24464da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 2447f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, Data._ID + "=?", 24484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 2449f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 245020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 245120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 245220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 245320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 245420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2455f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 245620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 245720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 245820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 245920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 246020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 246120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 246220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 246320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 246420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 24657a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 246620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 246720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 246820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 246924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Check for write profile permission if the data belongs to the profile. 247024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID); 247124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForRawContact(rawContactId, true); 247224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 2473a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2474d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov return rowHandler.delete(mDb, mTransactionContext, c); 247520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 247620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 247720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 247820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 247920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 248020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 2481ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 2482ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2483f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2484f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2485f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2486f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2487e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 2488ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2489ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 2490f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 249167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 2492f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 249367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 2494f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 2495ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2496dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final boolean isFavoritesGroup = mValues.getAsLong(Groups.FAVORITES) != null 2497dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ? mValues.getAsLong(Groups.FAVORITES) != 0 2498dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana : false; 2499dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2500f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2501f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 250273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 250373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2504f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 2505ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2506dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && isFavoritesGroup) { 2507dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // add all starred raw contacts to this group 2508dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String selection; 2509dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs; 2510dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (account == null) { 2511dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + " IS NULL AND " 2512dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContacts.ACCOUNT_TYPE + " IS NULL"; 2513dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = null; 2514dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2515dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + "=? AND " 2516dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContacts.ACCOUNT_TYPE + "=?"; 2517dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = new String[]{account.name, account.type}; 2518dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2519dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, 2520dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{RawContacts._ID, RawContacts.STARRED}, 2521dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, selectionArgs, null, null, null); 2522892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov try { 2523892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov while (c.moveToNext()) { 2524892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (c.getLong(1) != 0) { 2525892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov final long rawContactId = c.getLong(0); 2526892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov insertDataGroupMembership(rawContactId, result); 2527d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.markRawContactDirty(rawContactId); 2528892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 2529dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2530892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } finally { 2531892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov c.close(); 2532dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2533dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2534dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2535f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 25361a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2537ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 2538ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 2539ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 2540ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2541ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 25425aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 2543e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 25445aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 25451a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 25461a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2547e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 25481a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 2549e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 2550e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2551e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2552ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 255382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 25541f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 255582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 255682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 25570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 25584dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 25594dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 25600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 256182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 25624dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 25634dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 25644dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 25654dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 25661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25671f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2568dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 2569dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 257082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 2571f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 25722526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 2573dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 2574dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 2575dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 25762526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 25772526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 25781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 2579dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 2580dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 25810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 25820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 25830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 25840a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2585dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 2586dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 2587dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 25882a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov String mimeTypeIdIm = String.valueOf(mDbHelper.getMimeTypeIdForIm()); 2589dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 25902a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov String mimeTypeIdEmail = String.valueOf(mDbHelper.getMimeTypeIdForEmail()); 2591f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2592f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 2593f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 2594f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 2595f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2596f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 2597f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 25982526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 25992526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 26002526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 26012526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 26022526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 26032526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 26042526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 26052526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 2606dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 26072526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 26082526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 2609dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 26102526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 26112526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 2612dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 26132526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 26142526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 26152526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 26162526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 26172526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 26182526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 2619dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 26202526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 26212526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 2622dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2623dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 26241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 262582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 26262526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 26272526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 2628dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 262970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 263070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 26311f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 26321f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 2633de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 26342526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 26354394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID); 26361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 263767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 26385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 2639e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 26401f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 26411f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 26421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 26431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 26441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 264531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 264631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 264731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 26481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 26491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 265082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 2651a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 2652a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 2653a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 2654a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 2655a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2656a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2657a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 265882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 2659a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2660a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 266182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 266282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 266382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 266482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 266582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 2666a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 266782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 266882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 2669aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori mValues.put(StatusUpdates.CHAT_CAPABILITY, 2670aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori values.getAsString(StatusUpdates.CHAT_CAPABILITY)); 26711f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2672a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 2673a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 2674a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2675e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 26760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 267782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 267882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 26790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 26800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 26810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 26820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 26830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 26840a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 26850a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 26860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 26870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 26880a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 26890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 26900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2691a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 269278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.deleteStatusUpdate(dataId); 269382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 269482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 269578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.replaceStatusUpdate(dataId, timestamp, status, resPackage, iconResource, 269678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov labelResource); 2697a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 269878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.insertStatusUpdate(dataId, status, resPackage, iconResource, 269978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov labelResource); 2700e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2701e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 2702bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 2703a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 2704f4015ab9ab7c26b766b5331fbf6655b8c54877eaDmitri Plotnikov mContactAggregator.updateLastStatusUpdateId(contactId); 2705a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2706a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2707a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 27081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 27091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 27104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2711de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 2712bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2713b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 2714b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2715b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 2716f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2717f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2718508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 2719508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 272035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2721b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 272235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2723b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 2724b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 2725b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2726b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 2727b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 2728b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2729cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 2730cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 2731cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 2732cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2733cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2734d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2735d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 2736dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 27376bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 27386bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 27399fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 27402e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 27412e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 27422e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 2743fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2744fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 27452e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 27462e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 27472e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 2748dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 27492e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 27502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 27519fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 27529fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 27539fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 27549fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 27559fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 27569fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 2757a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 27589fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 27599fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 27609fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 27619fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 27629fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 27639fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 27649fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 27659fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 276660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 27679fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 27689fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 27699fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann Cursor c = query(db, lookupQb, null, selection, args, null, null, null); 27709fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 27719fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 27729fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 2773dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 27749fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 27759fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 27769fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 27779fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 27789fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 27799fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 27809fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 27819fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 27829fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 27839fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 27842971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 27852971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 2786fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, 2787fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 2788e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 27892971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 27902971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 27912971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 2792fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 2793fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 2794fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 27952971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27962971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 27972971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 27982971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 27992971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 28002971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 28012971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 28025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 28032971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 2804fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return deleteRawContact(rawContactId, mDbHelper.getContactId(rawContactId), 2805fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 2806508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2807508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 280820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 2809f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2810944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2811f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 281220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 281320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 281448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 281548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 281648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 281748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 2818508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2819f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 28204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 28214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 2822ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2823ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2824ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2825f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 28265aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 28272971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 28282971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 28292971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 28302971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 28312971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2832e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 28332971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 28342971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 28355aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 28362971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 28372971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 28382971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 28392971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 284081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 2841f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 284281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 28432971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 2844508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2845508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2846eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 284743880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2848e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 2849eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2850eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 285182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 28520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 28531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 28541f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 28553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 28563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 28573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), selection, selectionArgs); 28583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 28613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 28623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), 28633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemsColumns.CONCRETE_ID + "=?", 28643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 28653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 28683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 28693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItemPhotos(uri, new ContentValues(), selection, selectionArgs); 28703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 28733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 28743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 28753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 28763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItemPhotos(uri, new ContentValues(), 28773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " 28783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + StreamItemPhotos.STREAM_ITEM_ID + "=?", 28793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 28803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 288281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 288381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 28843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 288581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2886508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 28874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 28884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 28891c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 2890ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 2891b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 289294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 2893de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 289494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 289594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 289694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 289794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 2898f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 2899de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 290094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 290194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 290294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 2903f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 2904de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 290594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 290694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 29071a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 290894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 290994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 291094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 29115aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2912e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 29131a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 2914e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 2915e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 2916e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 2917dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int deleteContact(long contactId, boolean callerIsSyncAdapter) { 291824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForContact(contactId, true); 291996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 2920cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 292196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 292296b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 2923cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2924cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2925cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 2926dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 2927cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2928cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 2929cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 2930cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2931cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 29323826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 29333826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2934cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2935cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2936cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2937fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 293824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForRawContact(rawContactId, true); 29393389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 29403826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 29413826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2942f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 294314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2944fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov int count = mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 2945fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForContact(mDb, contactId); 2946fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 294733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 2948b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 2949dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 295033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 295133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 295233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 29530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 29549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 29559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 29569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 29579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 29589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 29599705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 29609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 29619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 29620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 29630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 29643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItems(Uri uri, ContentValues values, String selection, 29653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 29663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream items to be deleted, and check that they belong 29673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // to the account. 29683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 29693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = enforceModifyingAccountForStreamItems( 29703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann account, selection, selectionArgs); 29713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 29733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann for (long streamItemId : streamItemIds) { 29743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(streamItemId); 29753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mVisibleTouched = true; 29783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds.size(); 29793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItem(long streamItemId) { 29823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 29833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItemPhotos(streamItemId); 29843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return mDb.delete(Tables.STREAM_ITEMS, StreamItems._ID + "=?", 29853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 29863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(Uri uri, ContentValues values, String selection, 29893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 29903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream item photos to be deleted, and check that they 29913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // belong to the account. 29923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 29933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 29943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 29963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return mDb.delete(Tables.STREAM_ITEM_PHOTOS, selection, selectionArgs); 29973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(long streamItemId) { 30003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 30013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return mDb.delete(Tables.STREAM_ITEM_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID + "=?", 30023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 30033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 30043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 3005dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) { 300681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 300781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3008cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3009cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3010cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3011cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3012cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3013cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3014dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues, callerIsSyncAdapter); 3015cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3016cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 30174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3018de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3019de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3020bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3021b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3022b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3023b5a4add17815167d20a90645779df34cdf45280dFred Quintana 302435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 302500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 302600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3027b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3028b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 30291129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 3030d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.syncStateUpdated(rowId, data); 3031b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3032b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3033b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3034f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3035f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 303600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 303735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3038b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3039b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3040b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3041b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3042b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3043b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3044b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3045b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3046b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3047b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3048b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 304935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3050d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3051dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 305200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 305300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 305400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3055d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3056dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter); 3057c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3058c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3059c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 306024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 306124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Restrict update to the user's profile. 306224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro StringBuilder profileSelection = new StringBuilder(); 306324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileSelection.append(Contacts.IS_USER_PROFILE + "=1"); 306424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!TextUtils.isEmpty(selection)) { 306524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro profileSelection.append(" AND (").append(selection).append(")"); 306624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 306724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro count = updateContactOptions(values, profileSelection.toString(), selectionArgs, 306824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro callerIsSyncAdapter); 306924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 307024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 307124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 30722e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 30732e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 30742e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 30752e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 30762e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3077fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3078fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 30792e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 30802e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 30812e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 3082dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(contactId, values, callerIsSyncAdapter); 30832e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 30842e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 30852e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 30867d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 30877d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 30887d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 30897d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 30907d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 30917d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 30927d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 30937d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 30947d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 30957d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 309620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3097944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3098f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 309981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3100f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 310181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 310220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 310320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3104c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 310548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 310648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 310748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 310848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3109f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 311081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3111f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 311281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 311300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 311400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 31157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 31165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 31175ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 3118dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, selection, selectionArgs, callerIsSyncAdapter); 31197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 31207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 31217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 31225ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 312333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 31244529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 31254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 31264da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 3127dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND(" + selection + ")", selectionArgs, 3128dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 31294529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 31304da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 3131dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1, 3132dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 31334529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 31347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 31357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 31367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3137ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 31385aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3139f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 314081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3141f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 314281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3143ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3144ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3145ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3146ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3147ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 31484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 31494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 315073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 31515aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 31525aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 315381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3154f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 315581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3156ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3157ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3158ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3159127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 3160de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 3161b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3162b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3163b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3164eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3165e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3166e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 316743880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3168eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3169eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3170eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 31719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 31729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 31739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 31749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 31759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 31763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 31773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItems(uri, values, selection, selectionArgs); 31783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 31793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 31803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 31813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 31823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItems(uri, values, StreamItemsColumns.CONCRETE_ID + "=?", 31833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 31843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 31853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 31863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 31873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 31883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, selection, selectionArgs); 31893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 31903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 31913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 31923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 31933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 31943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 31953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotos.STREAM_ITEM_ID + "=?", new String[]{streamItemId}); 31963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 31973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 31983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 31993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 32003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 32013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 32023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 32033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " + 32043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?", 32053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 32063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 32073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 32083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 320972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case DIRECTORIES: { 3210bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanPackagesByUid(Binder.getCallingUid()); 321172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov count = 1; 3212d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 3213d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3214d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 321546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa case DATA_USAGE_FEEDBACK_ID: { 321646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (handleDataUsageFeedback(uri)) { 321746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 1; 321846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 321946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 0; 322046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 322146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa break; 322246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 322346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 322481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 322581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 3226f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 322781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 322800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 322900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 323000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 32314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 32324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 32339705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 32349705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 32359705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 32369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 32379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 32389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 32399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 32409705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 32419705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 32429705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 32439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 32449705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 32459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 32469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 32479705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 32489705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 32499705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 32509705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 32519705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 32529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 32539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 32549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 32559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 32569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 32573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItems(Uri uri, ContentValues values, String selection, 32583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 32593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream items can't be moved to a new raw contact. 32603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItems.RAW_CONTACT_ID); 32613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 32623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream items being updated belong to the account. 32633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 32643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItems(account, selection, selectionArgs); 32653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 32663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If there's been no exception, the update should be fine. 32673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return mDb.update(Tables.STREAM_ITEMS, values, selection, selectionArgs); 32683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 32693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 32703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItemPhotos(Uri uri, ContentValues values, String selection, 32713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 32723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream item photos can't be moved to a new stream item. 32733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItemPhotos.STREAM_ITEM_ID); 32743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 32753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream item photos being updated belong to the account. 32763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 32773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 32783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 32793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If there's been no exception, the update should be fine. 32803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return mDb.update(Tables.STREAM_ITEM_PHOTOS, values, selection, selectionArgs); 32813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 32823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 32839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 32849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 32859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 32869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 32879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 32889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 32899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 32909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 32919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 32929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 32939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 32949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 32959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 32969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 32979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 32989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 32999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 33009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 33019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 33029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 33039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 33049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 33059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 33069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 33079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 33089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 33099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 33109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 33119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 33129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 3313aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.CHAT_CAPABILITY, values, 3314aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori StatusUpdates.CHAT_CAPABILITY); 33159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 33169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 33179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 33185aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 3319f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 332073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3321ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3322ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 332373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 3324f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 332573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 332673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 332773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 332873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 332973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 333073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 333173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 333273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3333ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 33341a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 33351a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 333694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 33376ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 33381129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 33396ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 3340e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 33416ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 33426ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 33436ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 33446ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 33456ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 33466ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 33476ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 334824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 33496ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 3350ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 33516ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 33526ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 33536ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 33546ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 33556ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 33566ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 33576ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 33586ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 335994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 336094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 336194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 3362b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 3363b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 3364e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 33651a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 33661a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3367e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3368e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3369e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3370e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3371dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs, 3372dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 33734529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 33744529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 33754529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 33764529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 337773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 337897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 337997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 338097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0"); 338197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 338297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 33834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3384ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Cursor cursor = mDb.query(Views.RAW_CONTACTS, 338551bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 33864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 33874529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 33884529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 33894529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 3390dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContact(rawContactId, values, callerIsSyncAdapter); 33914529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 33924529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 33934529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 33944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 33954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 33964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 33974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 33984529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 33994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 3400dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContact(long rawContactId, ContentValues values, 3401dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 340224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 340324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Enforce profile permissions if the raw contact is in the user's profile. 340424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForRawContact(rawContactId, true); 340524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 340696b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 340796b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 340819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 340919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 341019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 3411ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 3412ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 341319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 341419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 341596b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1, null, null, null); 341619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 341719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 341819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 3419ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 3420ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 342119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 342219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 342319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 342419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 342519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 342619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 342719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 3428f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 342996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker int count = mDb.update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 34305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3431f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 3432f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 3433f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 3434f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 3435f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 3436f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 343769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode, false); 3438f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 3439f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 3440433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 3441dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 3442dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 3443dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana values.getAsLong(RawContacts.STARRED) != 0); 3444dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 34454529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3446dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 3447dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then update the 3448dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // favorites group membership based on whether or not this contact is starred. 3449dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // If it is starred, add a group membership, if one doesn't already exist 3450dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // otherwise delete any matching group memberships. 3451dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 3452dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean starred = 0 != DatabaseUtils.longForQuery(mDb, 3453dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SELECTION_STARRED_FROM_RAW_CONTACTS, 3454dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}); 3455dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred); 3456dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3457dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3458dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3459dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then add a 3460dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // group membership to the group marked as AutoAdd, if any. 3461dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 3462dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 3463433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3464dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3465285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 34662b7a632bba423357ae5641f94da6a2f71afc523bDmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(mDb, rawContactId); 3467285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 3468f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 3469f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 3470f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 3471f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 3472f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 347378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.resetNameVerifiedForOtherRawContacts(rawContactId); 3474f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 3475f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(mDb, rawContactId); 3476f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 347719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 3478d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mTransactionContext.rawContactInserted(rawContactId, 3479d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov new Account(accountName, accountType)); 348019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 34815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 34825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 348333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 348433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3485321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3486f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 348720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 348820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 348920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 34905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 349120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 349220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 349320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 349420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 349520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3496b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 349720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 349820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 349997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 350097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 350197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov Data.IS_READ_ONLY + "=0"); 350297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 350397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 3504653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 350520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3506653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3507653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 3508f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(uri, DataRowHandler.DataUpdateQuery.COLUMNS, 3509f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 3510653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 3511653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 351224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Check profile permission for the raw contact that owns each data record. 351324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = c.getLong(DataRowHandler.DataUpdateQuery.RAW_CONTACT_ID); 351424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForRawContact(rawContactId, true); 351524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 3516f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 351720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3518653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 3519653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 352020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 352120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3522653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 352320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 352420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3525f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 3526653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 3527653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 3528321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3529653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 3530f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String mimeType = c.getString(DataRowHandler.DataUpdateQuery.MIMETYPE); 3531a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3532d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (rowHandler.update(mDb, mTransactionContext, values, c, callerIsSyncAdapter)) { 3533813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 1; 3534813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } else { 3535813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 0; 3536a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 3537321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 3538321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 35398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 3540dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 35418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 3542ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Cursor cursor = mDb.query(Views.CONTACTS, 354324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro new String[] { Contacts._ID, Contacts.IS_USER_PROFILE }, selection, 35448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 35458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 35468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 35478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 354824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 354924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Check for profile write permission before updating a user's profile contact. 355024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro boolean isProfile = cursor.getInt(1) == 1; 355124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (isProfile) { 355224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(true); 355324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 355424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 3555dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateContactOptions(contactId, values, callerIsSyncAdapter); 35568c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 35578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 35588c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 35598c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 35608c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 35618c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 35628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 35638c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 35648c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 3565dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateContactOptions(long contactId, ContentValues values, 3566dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 3567d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 356824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // Check write permission if the contact is the user's profile. 356924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForContact(contactId, true); 357024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 35718c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3572b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3573d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3574b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 3575d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3576b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 3577d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3578b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3579d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3580b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3581d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 3582d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3583d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 35848c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 3585d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 3586d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 3587d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 35888c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 3589c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 35908c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3591c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 3592c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 35934da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 359497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?" 359597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov + " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1); 35968c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 3597dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) { 3598ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Cursor cursor = mDb.query(Views.RAW_CONTACTS, 3599dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?", 3600dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null, null, null); 3601dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 3602dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (cursor.moveToNext()) { 3603dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long rawContactId = cursor.getLong(0); 3604dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 3605dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.getAsLong(RawContacts.STARRED) != 0); 3606dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3607dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 3608dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana cursor.close(); 3609dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3610dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3611dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 36128c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 36138c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 36148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 3615b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 36168c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3617b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 36188c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 3619b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 36208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 3621b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 36228c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3623b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 36248c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 36258c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 36269b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori int rslt = mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 36276e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 36289b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 36299b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 36309b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 36319b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 36329b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 36339b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 3634f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3635d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 3636127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 3637127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 36380c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 36390c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 364080c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 3641ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId1; 3642ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId2; 36430c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 36440c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 36450c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 36460c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 36470c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 36480c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 3649b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3650127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 36510c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 36524da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 36534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 36540c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 36554da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 36564da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 36570c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 36586bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 36596bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 36600c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 36610c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 36620c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 36630c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 3664127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 3665127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 36663389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 366769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1, 366869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 366969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2, 367069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 3671dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 3672bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mContactAggregator.aggregateContact(mTransactionContext, db, rawContactId1); 3673bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mContactAggregator.aggregateContact(mTransactionContext, db, rawContactId2); 3674127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 3675127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 3676127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 3677127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 3678b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3679b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 368070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 3681bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 36823826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 36833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 3684bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected boolean updateAccountsInBackground(Account[] accounts) { 3685f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 3686e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov boolean accountsChanged = false; 3687627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 368849d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 368970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 369070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 3691dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana findValidAccounts(existingAccounts); 3692743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 3693743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // Add a row to the ACCOUNTS table for each new account 3694743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 3695743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov if (!existingAccounts.contains(account)) { 3696e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 3697743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 3698743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov + ", " + RawContacts.ACCOUNT_TYPE + ") VALUES (?, ?)", 3699743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov new String[] {account.name, account.type}); 3700743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 3701743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 370248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 3703627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 3704743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // in the accountsToDelete set will be extra accounts whose data must be deleted. 3705627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 3706627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 3707627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 370870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 370970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 371033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov if (!accountsToDelete.isEmpty()) { 3711e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 3712e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov for (Account account : accountsToDelete) { 3713e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov Log.d(TAG, "removing data for removed account " + account); 3714e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 3715e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 3716e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 3717e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 3718e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 3719e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 3720e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 3721e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 3722e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "SELECT " + RawContacts._ID + 3723e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 3724e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3725e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 3726e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 3727e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 3728e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3729e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 3730e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 3731e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 3732e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 3733e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 3734e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDb.execSQL( 3735e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 3736e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 3737e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + "=?", params); 3738d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mDb.execSQL( 3739d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov "DELETE FROM " + Tables.DIRECTORIES + 3740d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " WHERE " + Directory.ACCOUNT_NAME + "=?" + 3741d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " AND " + Directory.ACCOUNT_TYPE + "=?", params); 37424458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov resetDirectoryCache(); 3743e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 3744e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 374533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 374633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 3747e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov // names or photos. If so, fix up those contacts. 374833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 374933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Cursor cursor = mDb.rawQuery("SELECT " + Contacts._ID + 375033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 375133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 375269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 375369cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 375469cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 375533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 375633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 375769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 375869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 375933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 376033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 376133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 376233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 376333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 376433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 376533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 376633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 376733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 3768bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mContactAggregator.updateAggregateData(mTransactionContext, contactId); 376933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 3770e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDbHelper.updateAllVisible(); 3771bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 377233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 377333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 3774e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (accountsChanged) { 3775e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 3776e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 377770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 377870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 377970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 378070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 378173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 37823826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 37833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (accountsChanged) { 37843826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateContactsAccountCount(accounts); 37853826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 37863826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 37873826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 3788afb84050536a4472c13efc0e996d31132d254605Dmitri Plotnikov return accountsChanged; 378970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 3790619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 37913826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateContactsAccountCount(Account[] accounts) { 37923826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov int count = 0; 37933826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov for (Account account : accounts) { 37943826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (isContactsAccount(account)) { 37953826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov count++; 37963826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 37973826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 37983826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mContactsAccountCount = count; 37993826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 38003826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 38013826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov protected boolean isContactsAccount(Account account) { 38023826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov final IContentService cs = ContentResolver.getContentService(); 38033826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov try { 38043826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return cs.getIsSyncable(account, ContactsContract.AUTHORITY) > 0; 38053826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } catch (RemoteException e) { 38063826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov Log.e(TAG, "Cannot obtain sync flag for account: " + account, e); 38073826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return false; 38083826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 38093826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 38103826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 381172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPackageChanged(String packageName) { 3812bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_DIRECTORIES, packageName); 3813d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3814d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3815619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 3816627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 3817627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 3818dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void findValidAccounts(Set<Account> validAccounts) { 3819743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov Cursor c = mDb.rawQuery( 3820743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "SELECT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 3821743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " FROM " + Tables.ACCOUNTS, null); 3822627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 3823627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 3824dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!c.isNull(0) || !c.isNull(1)) { 3825627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 3826627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3827627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3828627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 3829627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 3830627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3831627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3832627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 38334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 38344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 38354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 383615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 383715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mReadAccessLatch); 383815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 3839d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY); 3840385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directory == null) { 38413716f1447ceb21180d1301790eabd8b9453f486dDave Santoro return wrapCursor(uri, 38423716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1)); 3843385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directory.equals("0")) { 38443716f1447ceb21180d1301790eabd8b9453f486dDave Santoro return wrapCursor(uri, 38453716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 38463716f1447ceb21180d1301790eabd8b9453f486dDave Santoro Directory.DEFAULT)); 3847d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } else if (directory.equals("1")) { 38483716f1447ceb21180d1301790eabd8b9453f486dDave Santoro return wrapCursor(uri, 38493716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 38503716f1447ceb21180d1301790eabd8b9453f486dDave Santoro Directory.LOCAL_INVISIBLE)); 3851d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3852d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3853d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryInfo directoryInfo = getDirectoryAuthority(directory); 3854d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo == null) { 3855a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov Log.e(TAG, "Invalid directory ID: " + uri); 3856a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov return null; 3857d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3858d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3859d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Builder builder = new Uri.Builder(); 3860d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.scheme(ContentResolver.SCHEME_CONTENT); 3861d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.authority(directoryInfo.authority); 3862d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.encodedPath(uri.getEncodedPath()); 3863d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountName != null) { 3864d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, directoryInfo.accountName); 3865d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3866d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountType != null) { 3867d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, directoryInfo.accountType); 3868d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 38692e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 38702e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limit = getLimit(uri); 38712e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov if (limit != null) { 38722e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov builder.appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, limit); 38732e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov } 38742e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 3875d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Uri directoryUri = builder.build(); 387609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 387709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (projection == null) { 387809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov projection = getDefaultProjection(uri); 387909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 388009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 3881332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov Cursor cursor = getContext().getContentResolver().query(directoryUri, projection, selection, 3882d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs, sortOrder); 38836ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 38846ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (cursor == null) { 38856ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 38866ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 38876ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 3888547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro CrossProcessCursor crossProcessCursor = getCrossProcessCursor(cursor); 3889547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (crossProcessCursor != null) { 3890547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro return wrapCursor(uri, cursor); 3891547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } else { 3892547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro return matrixCursorFromCursor(wrapCursor(uri, cursor)); 3893547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 38943716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 38953716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 3896547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro private Cursor wrapCursor(Uri uri, Cursor cursor) { 3897547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 3898547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro // If the cursor doesn't contain a snippet column, don't bother wrapping it. 3899547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (cursor.getColumnIndex(SearchSnippetColumns.SNIPPET) < 0) { 3900547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro return cursor; 3901547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 3902547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 39033716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Parse out snippet arguments for use when snippets are retrieved from the cursor. 39043716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String[] args = null; 39053716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String snippetArgs = 39063716f1447ceb21180d1301790eabd8b9453f486dDave Santoro getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 39073716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (snippetArgs != null) { 39083716f1447ceb21180d1301790eabd8b9453f486dDave Santoro args = snippetArgs.split(","); 39093716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 39103716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 39113716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String query = uri.getLastPathSegment(); 39123716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String startMatch = args != null && args.length > 0 ? args[0] 39133716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_START_MATCH; 39143716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String endMatch = args != null && args.length > 1 ? args[1] 39153716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_END_MATCH; 39163716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String ellipsis = args != null && args.length > 2 ? args[2] 39173716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_ELLIPSIS; 39183716f1447ceb21180d1301790eabd8b9453f486dDave Santoro int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 39193716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 39203716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 3921547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro return new SnippetizingCursorWrapper(cursor, query, startMatch, endMatch, ellipsis, 3922547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro maxTokens); 39236ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 39246ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 39256ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov private CrossProcessCursor getCrossProcessCursor(Cursor cursor) { 39266ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov Cursor c = cursor; 39276ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (c instanceof CrossProcessCursor) { 39286ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return (CrossProcessCursor) c; 39296ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else if (c instanceof CursorWindow) { 39306ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return getCrossProcessCursor(((CursorWrapper) c).getWrappedCursor()); 39316ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else { 39326ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 39336ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 39346ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 39356ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 39366ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public MatrixCursor matrixCursorFromCursor(Cursor cursor) { 39376ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 39386ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov int numColumns = cursor.getColumnCount(); 39396ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov String data[] = new String[numColumns]; 39406ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov cursor.moveToPosition(-1); 39416ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov while (cursor.moveToNext()) { 39426ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov for (int i = 0; i < numColumns; i++) { 39436ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov data[i] = cursor.getString(i); 39446ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 39456ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov newCursor.addRow(data); 3946332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov } 39476ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return newCursor; 3948d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3949d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3950d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final class DirectoryQuery { 3951d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 3952d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory._ID, 3953d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.DIRECTORY_AUTHORITY, 3954d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_NAME, 3955d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_TYPE 3956d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov }; 3957d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3958d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int DIRECTORY_ID = 0; 3959d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int AUTHORITY = 1; 3960d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_NAME = 2; 3961d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_TYPE = 3; 3962d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3963d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3964d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 3965d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Reads and caches directory information for the database. 3966d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 3967d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private DirectoryInfo getDirectoryAuthority(String directoryId) { 39684458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized (mDirectoryCache) { 39694458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (!mDirectoryCacheValid) { 39704458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.clear(); 397149d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 397249d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Cursor cursor = db.query(Tables.DIRECTORIES, 39734458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryQuery.COLUMNS, 39744458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov null, null, null, null, null); 39754458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov try { 39764458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov while (cursor.moveToNext()) { 39774458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryInfo info = new DirectoryInfo(); 39784458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov String id = cursor.getString(DirectoryQuery.DIRECTORY_ID); 39794458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.authority = cursor.getString(DirectoryQuery.AUTHORITY); 39804458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME); 39814458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE); 39824458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.put(id, info); 39834458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 39844458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } finally { 39854458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov cursor.close(); 3986d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 39874458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = true; 3988d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3989d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 39904458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov return mDirectoryCache.get(directoryId); 39914458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 3992d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3993d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 399472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void resetDirectoryCache() { 39954458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized(mDirectoryCache) { 39964458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = false; 39974458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 399872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 399972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 4000d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public Cursor queryLocal(Uri uri, String[] projection, String selection, String[] selectionArgs, 4001385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov String sortOrder, long directoryId) { 4002bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 4003bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 4004bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 40050b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 4006b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 400735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4008d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 40091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 4010c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 4011c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4012a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 40134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 401435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 4015b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 401635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 401735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4018d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 4019763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 402024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro boolean existingWhere = appendLocalDirectorySelectionIfNeeded(qb, directoryId); 402124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro appendProfileRestriction(qb, uri, Contacts.IS_USER_PROFILE, existingWhere); 402224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro sortOrder = prependProfileSortIfNeeded(uri, sortOrder); 4023619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 4024619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4025619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4026d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 40274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 402824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForContact(contactId, false); 4029763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 40304da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 40314da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 40326bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 40336bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 40346bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 40355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 40365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 40375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 40385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 40395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 4040fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4041fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 40425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 4043a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 40445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 40455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 40465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 404724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForContact(contactId, false); 40485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4049763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 4050a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4051a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 4052a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4053a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 4054a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 40555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 40565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4059763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 40604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 40614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 40624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 40635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 40645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 40655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 40662149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_DATA: 40672149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_ID_DATA: { 40682149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 40692149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov int segmentCount = pathSegments.size(); 40702149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount < 4) { 40712149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 40722149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov "Missing a lookup key", uri)); 40732149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 40742149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String lookupKey = pathSegments.get(2); 40752149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount == 5) { 40762149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 407724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForContact(contactId, false); 40782149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 40792149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(lookupQb, uri, projection, false); 4080a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 4081a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 4082a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4083a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey); 4084a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 40852149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov return c; 40862149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 40872149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 40882149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov // TODO see if the contact exists but has no data rows (rare) 40892149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 40902149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 40912149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 409224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long contactId = lookupContactIdByLookupKey(db, lookupKey); 409324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForContact(contactId, false); 40942149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 409524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 40962149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov qb.appendWhere(" AND " + Data.CONTACT_ID + "=?"); 40972149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov break; 40982149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 40992149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 41003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_ID_STREAM_ITEMS: { 41013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(uri.getPathSegments().get(1)); 41023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceProfilePermissionForContact(contactId, false); 41033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 41043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 41053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(RawContactsColumns.CONCRETE_CONTACT_ID + "=?"); 41063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 41073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 41083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 41093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_STREAM_ITEMS: 41103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_ID_STREAM_ITEMS: { 41113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<String> pathSegments = uri.getPathSegments(); 41123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int segmentCount = pathSegments.size(); 41133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount < 4) { 41143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann throw new IllegalArgumentException(mDbHelper.exceptionMessage( 41153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann "Missing a lookup key", uri)); 41163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 41173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String lookupKey = pathSegments.get(2); 41183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount == 5) { 41193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(pathSegments.get(3)); 41203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceProfilePermissionForContact(contactId, false); 41213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 41223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(lookupQb); 41233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 41243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann projection, selection, selectionArgs, sortOrder, groupBy, limit, 41253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann RawContacts.CONTACT_ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 41263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c != null) { 41273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return c; 41283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 41293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 41303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 41313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 41323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = lookupContactIdByLookupKey(db, lookupKey); 41333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceProfilePermissionForContact(contactId, false); 41343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 41353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(RawContacts.CONTACT_ID + "=?"); 41363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 41373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 41383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 4139f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 414042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 414124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long contactId = lookupContactIdByLookupKey(db, lookupKey); 414224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForContact(contactId, false); 4143ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 4144f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 41454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 414624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 41474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 4148f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 4149f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 4150f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 415142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 415242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 415342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 415442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return db.rawQuery( 415542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 415642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 415742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 415842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 415942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 416042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 4161ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 4162916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 4163ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 4164916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 4165ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 41667ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet( 41677ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov qb, uri, projection, filterParam, directoryId); 416824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro appendProfileRestriction(qb, uri, Contacts.IS_USER_PROFILE, false); 416924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro sortOrder = prependProfileSortIfNeeded(uri, sortOrder); 4170ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4171ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4172ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4173ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 4174ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 41752f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Basically the resultant SQL should look like this: 41762f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing starred items) 41772f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 41782f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing frequently contacted items) 41792f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // ORDER BY ... 41802f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 41812f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final boolean phoneOnly = readBooleanQueryParameter( 41822f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa uri, ContactsContract.STREQUENT_PHONE_ONLY, false); 41832f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (match == CONTACTS_STREQUENT_FILTER && uri.getPathSegments().size() > 3) { 41844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 41854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4186e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 41875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 41882f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa selection = DbQueryUtils.concatenateClauses(selection, sb.toString()); 41894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 41904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 41912f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] subProjection = null; 41925e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 41932f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa subProjection = appendProjectionArg(projection, TIMES_USED_SORT_COLUMN); 41945e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 41955e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 41964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 41972f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, 41982f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa false /* for frequent */, phoneOnly); 41992f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setProjectionMap(sStrequentStarredProjectionMap); 42002f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 42012f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa selection, Contacts.IS_USER_PROFILE + "=0")); 42022f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 42032f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String starredQuery = qb.buildQuery(subProjection, 420424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Contacts.STARRED + "=1", Contacts._ID, null, null, null); 4205d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 42062f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Reset the builder. 4207d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 42082f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 42092f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Build the second query for frequent 42102f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, 42112f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa true /* for frequent */, phoneOnly); 421224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.setProjectionMap(sStrequentFrequentProjectionMap); 42132f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 42142f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa selection, Contacts.IS_USER_PROFILE + "=0")); 42152f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 42162f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String frequentQuery = qb.buildQuery(subProjection, 42172f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa "(" + Contacts.STARRED + " =0 OR " + Contacts.STARRED + " IS NULL)", 421824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Contacts._ID, null, null, null); 4219d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4220d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 42212f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String unionQuery = 42222f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 42232f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa STREQUENT_ORDER_BY, STREQUENT_LIMIT); 42242f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 42252f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Here, we need to use selection / selectionArgs (supplied from users) "twice", 42262f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // as we want them both for starred items and for frequently contacted items. 42272f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // 42282f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // e.g. if the user specify selection = "starred =?" and selectionArgs = "0", 42292f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // the resultant SQL should be like: 42302f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 42312f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 42322f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 42332f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] doubledSelectionArgs = null; 42342f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (selectionArgs != null) { 42352f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final int length = selectionArgs.length; 42362f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa doubledSelectionArgs = new String[length * 2]; 42377d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, 0, length); 42387d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, length, length); 42392f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 42402f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 42412f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa Cursor cursor = db.rawQuery(unionQuery, doubledSelectionArgs); 42422f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (cursor != null) { 42432f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa cursor.setNotificationUri(getContext().getContentResolver(), 4244d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 4245d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 42462f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa return cursor; 4247d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4248d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4249ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 4250763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4251b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 425271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 42534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 4254b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4255b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 4256b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4257b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 425824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 425924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(false); 426024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 426124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.appendWhere(Contacts.IS_USER_PROFILE + "=1"); 426224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 426324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 426424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 426524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: { 426624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(false); 426724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForEntities(qb, uri, projection); 426824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.appendWhere(" AND " + Contacts.IS_USER_PROFILE + "=1"); 426924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 427024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 427124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 427224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: { 427324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(false); 427424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 427524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.appendWhere(" AND " + RawContacts.RAW_CONTACT_IS_USER_PROFILE + "=1"); 427624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 427724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 427824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 427924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA_ID: { 428024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(false); 428124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 428224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 428324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.appendWhere(" AND " + Data._ID + "=? AND " 428424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro + RawContacts.RAW_CONTACT_IS_USER_PROFILE + "=1"); 428524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 428624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 428724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 428824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: { 428924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(false); 4290ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 429124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.setProjectionMap(sContactsVCardProjectionMap); 429224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.appendWhere(Contacts.IS_USER_PROFILE + "=1"); 429324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 429424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 429524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 4296a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_DATA: { 42974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 429882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 42994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 43004da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 43016bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 43026bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 430300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 4304a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 43053653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 430682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 43074da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 43084da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 43093653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 43103653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 43113653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 43123653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4313a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_ENTITIES: { 4314a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 4315a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 4316a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 4317a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 4318a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 4319a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4320a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4321a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ENTITIES: 4322a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ID_ENTITIES: { 4323a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 4324a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov int segmentCount = pathSegments.size(); 4325a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount < 4) { 4326a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4327a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov "Missing a lookup key", uri)); 4328a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4329a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lookupKey = pathSegments.get(2); 4330a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount == 5) { 4331a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 4332a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4333a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(lookupQb, uri, projection); 4334a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 4335a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4336a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri, 4337a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4338a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.CONTACT_ID, contactId, 4339a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.LOOKUP_KEY, lookupKey); 4340a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 4341a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 4342a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4343a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4344a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4345a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 4346a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 4347a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 4348a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?"); 4349a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 4350a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4351a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 43523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 43533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 43543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 43553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 43563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 43573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 43583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 43593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 43603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemsColumns.CONCRETE_ID + "=?"); 43613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 43623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 43633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 43643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_LIMIT: { 43653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann MatrixCursor cursor = new MatrixCursor( 43663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{StreamItems.MAX_ITEMS, StreamItems.PHOTO_MAX_BYTES}, 1); 43673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann cursor.addRow( 43683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new Object[]{ 43693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann MAX_STREAM_ITEMS_PER_RAW_CONTACT, 43703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mMaxStreamItemPhotoSizeBytes 43713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann }); 43723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return cursor; 43733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 43743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 43753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 43763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 43773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 43783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 43793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 43803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 43813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 43823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 43833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 43843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?"); 43853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 43863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 43873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 43883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 43893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 43903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 43913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 43923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemPhotoId); 43933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 43943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=? AND " + 43953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=?"); 43963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 43973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 43983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 43994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 440082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 440189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 44022815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 44032815f58f72f109790585931f601a63ddc02536a5Evan Millar } 44042815f58f72f109790585931f601a63ddc02536a5Evan Millar 440548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 440682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 44074da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 440848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 44094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 441048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 441148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 441248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 4413ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 441446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 441546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 441646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 441746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_CALL; 441846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 441946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 442089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 4421ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 44224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 44234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4424a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 44255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 442645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 44275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 44285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 44295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 4430155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN " + 4431155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 4432155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 4433155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 4434155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 4435155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 4436155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE " + SearchIndexColumns.NAME + " MATCH "); 44372352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filterParam) + "*"); 4438155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(")"); 44395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 444045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 44415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 4443892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filterParam); 4444892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (!TextUtils.isEmpty(number)) { 44455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 44465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 44475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 4449892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov " IN (SELECT DISTINCT " + PhoneLookupColumns.DATA_ID 4450892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 4451892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 4452892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append(number); 4453892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append("%')"); 445445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 445545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 445645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 445745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 445845d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 445945d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 446045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 44615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 44625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4463a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 4464ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 44655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 4466a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 446746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 446846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 446946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + PHONE_FILTER_SORT_ORDER; 447046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 447146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = PHONE_FILTER_SORT_ORDER; 447246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 4473a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 4474ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4475ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4476ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 44774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 447882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 447989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 44804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 44814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 44824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 448348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 448482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 44854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 44864da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 44874da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 448848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 448948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 449048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 44915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 449282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 449389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 44944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 449508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 449608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String address = mDbHelper.extractAddressFromEmailAddress(email); 449708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 449808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 44994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 4500ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4501ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4502ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 45035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 450446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 450546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 450646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 450746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT; 450846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 450946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 451007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 45117d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa 451207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 451307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 451407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 451507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 451607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 451707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 45185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 451907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 452007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 452107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 452207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 452307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 452407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 452507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 452607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 452707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 45282a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "="); 45292a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForEmail()); 45302a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(" AND " + Data.DATA1 + " LIKE "); 453107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 453220938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 4533155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append( 4534155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " UNION SELECT " + Data._ID + 4535155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.DATA + 4536155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "="); 4537155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(mDbHelper.getMimeTypeIdForEmail()); 4538155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(" AND " + Data.RAW_CONTACT_ID + " IN " + 4539155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 4540155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 4541155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 4542155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 4543155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 4544155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE " + SearchIndexColumns.NAME + " MATCH "); 45452352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filterParam) + "*"); 4546155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(")"); 45475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4549a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 45505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 4552a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 455346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 455446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 455546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + EMAIL_FILTER_SORT_ORDER; 45567d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } else { 45577d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa sortOrder = EMAIL_FILTER_SORT_ORDER; 45587d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } 4559a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 45605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 45615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 4563ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 456482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 456589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 456689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 4567ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4568ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4569ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 457048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 457182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 45724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 457348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 457448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 45754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 457648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 457748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 457848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 45795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 4580763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 458124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro appendProfileRestriction(qb, uri, RawContacts.RAW_CONTACT_IS_USER_PROFILE, true); 45824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 45834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 45844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 45855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 45865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 458724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForRawContact(rawContactId, false); 4588763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 45894da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 45904da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 45914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 45924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 45934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 45945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 45955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 459682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 45974da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 45984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 459924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro appendProfileRestriction(qb, uri, RawContacts.RAW_CONTACT_IS_USER_PROFILE, true); 460024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 460124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 460224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 46033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 46043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 46053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceProfilePermissionForRawContact(rawContactId, false); 46063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 46073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 46083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=?"); 46093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 46103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 461124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 461224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: { 461324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(false); 461424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForRawContacts(qb, uri); 461524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.appendWhere(" AND " + RawContacts.RAW_CONTACT_IS_USER_PROFILE + "=1"); 461624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 461724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 461824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 461924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: { 462024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(false); 462124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = ContentUris.parseId(uri); 462224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 462324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForRawContacts(qb, uri); 462424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.appendWhere(" AND " + RawContacts.RAW_CONTACT_IS_USER_PROFILE + "=1 AND " 462524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro + RawContacts._ID + "=?"); 462624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 462724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 462824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 462924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 463024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(false); 463124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(2)); 463224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 463324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 463424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.appendWhere(" AND " + RawContacts.RAW_CONTACT_IS_USER_PROFILE + "=1 AND " 463524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro + Data.RAW_CONTACT_ID + "=?"); 463624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 463724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 463824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 463924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID_ENTITIES: { 464024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(false); 464124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(2)); 464224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 464324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForRawEntities(qb, uri); 464424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.appendWhere(" AND " + RawContacts.RAW_CONTACT_IS_USER_PROFILE + "=1 AND " 464524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro + RawContacts._ID + "=?"); 4646e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4647e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4648e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 4649e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 465082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 465124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro appendProfileRestriction(qb, uri, RawContacts.RAW_CONTACT_IS_USER_PROFILE, true); 4652e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4653e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4654e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 46554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 465624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long dataId = ContentUris.parseId(uri); 465724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForData(dataId, false); 465882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 46594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 46604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 4661a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 4662a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 4663a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 4664a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 46654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4666a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 4667a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 4668a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 4669892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sortOrder = " length(lookup.normalized_number) DESC"; 4670a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4671a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4672e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 4673e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov String numberE164 = PhoneNumberUtils.formatNumberToE164(number, 4674e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov mDbHelper.getCurrentCountryIso()); 4675892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String normalizedNumber = 4676892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.normalizeNumber(number); 4677892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, normalizedNumber, numberE164); 4678e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 4679e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 4680e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 4681e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 4682a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 4683a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4684a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4685ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 4686ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 4687ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 468889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4689ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4690ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4691ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4692ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 4693ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 4694ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 46954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 46964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 4697ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4698ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4699ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4700ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 4701ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS + " AS groups"); 4702ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 470389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 470489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 4705ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4706ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4707ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4708b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 47090c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 4710b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 4711b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 4712b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4713b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 471431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 4715d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 47162d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 47172d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 47182d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 47192d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 472031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 4721d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 4722d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 472331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 472431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 472531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 472631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 47275b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ArrayList<AggregationSuggestionParameter> parameters = null; 47285b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov List<String> query = uri.getQueryParameters("query"); 47295b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov if (query != null && !query.isEmpty()) { 47305b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters = new ArrayList<AggregationSuggestionParameter>(query.size()); 47315b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov for (String parameter : query) { 47325b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov int offset = parameter.indexOf(':'); 47335b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters.add(offset == -1 47345b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ? new AggregationSuggestionParameter( 473576dfa406e2cde19c824983c37fc92c1c5bf63eecDaniel Lehmann AggregationSuggestions.PARAMETER_MATCH_NAME, 47365b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter) 47375b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov : new AggregationSuggestionParameter( 47385b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(0, offset), 47395b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(offset + 1))); 47405b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 47415b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 47425b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 4743763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 47447581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 47457581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 47465b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov maxSuggestions, filter, parameters); 474731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 474831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4749eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 4750eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 4751eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 475289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4753e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4754e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 4755e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 4756b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 4757e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 475882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4759b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 4760e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4761e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 476282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4763b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 4764e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4765e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4766e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4767eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 4768eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 4769eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 477082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 47710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 47725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 47735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 47745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 477582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 47760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 47774da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 47784da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 47795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 47805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 47815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 4782c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 4783174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery( 4784174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov db, uri, projection, limit); 4785c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4786c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4787c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 47882d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 4789174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String filter = getQueryParameter( 4790174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov uri, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); 4791174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh( 4792174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov db, projection, lookupKey, filter); 4793c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4794c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 47951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 4796ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 47971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 47981b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 47991b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 48001b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 4801ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 48021b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 48031b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 48041b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 48051b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 48061b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 4807ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 48081b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 48091b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 48101b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 48111b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 48121b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 4813ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 48141b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 481571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 48161b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 48171b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 48181b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 481946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 4820a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 482146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 482246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 482346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 482446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 482546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 4826a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 48274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 48284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 482946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 483046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 483146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 483209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 483309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 483409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 483509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 4836d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES : { 4837d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 4838d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 4839d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 4840d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4841d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4842d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID : { 4843385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov long id = ContentUris.parseId(uri); 4844d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 4845d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 4846385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(id)); 4847d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Directory._ID + "=?"); 4848d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 4849d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4850d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 48517a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov case COMPLETE_NAME: { 48527a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return completeName(uri, projection); 48537a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 48547a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 48554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 4856f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 4857c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 48584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 486009e69522745551522c55dff27424496f255def46Daniel Lehmann qb.setStrict(true); 48617f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 4862ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 4863ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 4864ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 4865ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov cursor = bundleLetterCountExtras(cursor, db, qb, selection, selectionArgs, sortOrder); 4866ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4867ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 48685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 48705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 48715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 48725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 4873038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 4874038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 4875038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 4876038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 48775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 48785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 48794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 48804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 48814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 48834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 488509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 488609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 488709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 488809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 488909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 489009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 489109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 489209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 489309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 489409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 489509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 489609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 489709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 489809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 489909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 490009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 4901a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 4902a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Runs the query with the supplied contact ID and lookup ID. If the query succeeds, 4903a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * it returns the resulting cursor, otherwise it returns null and the calling 4904a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * method needs to resolve the lookup key and rerun the query. 4905a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 4906a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private Cursor queryWithContactIdAndLookupKey(SQLiteQueryBuilder lookupQb, 4907a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteDatabase db, Uri uri, 4908a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection, String selection, String[] selectionArgs, 4909a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String sortOrder, String groupBy, String limit, 4910a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn, long contactId, String lookupKeyColumn, String lookupKey) { 4911a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] args; 4912a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (selectionArgs == null) { 4913a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[2]; 4914a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 4915a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[selectionArgs.length + 2]; 4916a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 4917a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4918a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[0] = String.valueOf(contactId); 4919a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[1] = Uri.encode(lookupKey); 4920a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(contactIdColumn + "=? AND " + lookupKeyColumn + "=?"); 4921a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 4922a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov groupBy, limit); 4923a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c.getCount() != 0) { 4924a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 4925a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4926a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4927a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov c.close(); 4928a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return null; 4929a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 493009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 4931bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 4932bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 4933bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 4934bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 4935ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4936bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 4937bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 4938ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 4939ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4940bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 4941bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 4942bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 4943bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 494424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // The first letter of the sort key column is what is used for the index headings, except 494524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // in the case of the user's profile, in which case it is empty. 494624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public static final String SECTION_HEADING_TEMPLATE = 494724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "(CASE WHEN %1$s=1 THEN '' ELSE SUBSTR(%2$s,1,1) END)"; 494824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 4949de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 4950ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4951ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4952ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 4953ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 4954ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 4955ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 4956ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 4957ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder) { 4958ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 4959ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4960ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 4961ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 4962ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 4963ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 4964ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 496524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 496624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // If the sort order contains one of the "is_profile" columns, we need to strip it out 496724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // first. 496824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (sortOrder.contains(Contacts.IS_USER_PROFILE) 496924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro || sortOrder.contains(RawContacts.RAW_CONTACT_IS_USER_PROFILE)) { 497024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String[] splitOrderClauses = sortOrder.split(","); 497124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro StringBuilder rejoinedClause = new StringBuilder(); 497224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro for (String orderClause : splitOrderClauses) { 497324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!orderClause.contains(Contacts.IS_USER_PROFILE) 497424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro && !orderClause.contains(RawContacts.RAW_CONTACT_IS_USER_PROFILE)) { 497524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (rejoinedClause.length() > 0) { 497624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro rejoinedClause.append(", "); 497724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 497824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro rejoinedClause.append(orderClause.trim()); 497924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 498024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 498124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro sortOrder = rejoinedClause.toString(); 498224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 498324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 4984ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 4985ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 4986ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 4987ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 4988ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 4989ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 4990ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4991ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 4992ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 4993ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4994ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4995bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 4996ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 499724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 499824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // The user profile column varies depending on the view. 4999ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann String profileColumn = qb.getTables().contains(Views.CONTACTS) 500024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro ? Contacts.IS_USER_PROFILE 500124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro : RawContacts.RAW_CONTACT_IS_USER_PROFILE; 500224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String sectionHeading = String.format( 500324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro AddressBookIndexQuery.SECTION_HEADING_TEMPLATE, profileColumn, sortKey); 5004bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 500524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro sectionHeading + " AS " + AddressBookIndexQuery.LETTER); 5006bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5007bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 5008bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 5009bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 5010bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 5011bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 5012bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 5013bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 5014ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 501524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "GET_PHONEBOOK_INDEX(" + sectionHeading + ",'" + locale + "')" 5016bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 5017ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 5018ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov "COUNT(" + Contacts._ID + ") AS " + AddressBookIndexQuery.COUNT); 5019ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 5020ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5021f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 5022ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 5023ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 5024ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5025ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 5026f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 5027ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 5028ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 5029bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 5030bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 5031bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5032bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 5033bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 5034bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 5035ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 5036f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 5037bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 5038bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 5039bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 5040bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 5041bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 5042bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 5043bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 5044bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 5045bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 5046bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 5047bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5048bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 5049bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 5050bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 5051bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 5052bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5053bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 5054bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 5055bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 5056ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5057ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5058e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov return new AddressBookCursor((CrossProcessCursor) cursor, titles, counts); 5059ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 5060f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 5061ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5062ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5063ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 50642d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 506592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 506692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 506792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 506892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 50692d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 50702d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 50715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 50725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 50735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 507492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 507592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 507692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 507792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 507892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 507992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 508092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 508192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 508292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 508392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 508492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 508592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 508692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 508792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 508892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 508992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 509092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 509192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 509292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 50935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 50945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 50975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 51005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 51015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 51035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 51045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 51055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 51065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 51075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 51085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 51105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 51115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 51125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 51135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 51165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 51175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 51185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 51195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 51205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 512192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 51225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 51235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 51245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 51275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 51285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 51305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 51315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 51325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 51335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 51345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 51355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 51365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 51375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 51385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 51395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 514092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 514192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 51425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 51435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 51445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 51455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 51495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 51505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 51535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 515592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 515692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 51575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 51595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 51605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 51615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 516292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 51635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 51645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 51665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 51675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 516892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 51695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 517192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 517292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 517392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 517492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 51755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 51765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 517792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 517892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 517992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 51805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 518292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 518392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 51845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 518592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 518692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 518792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 518892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 518992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountType = c.getString(LookupByRawContactIdQuery.ACCOUNT_TYPE); 519092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 519192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 519292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 519392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 519492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 519592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 519692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 519792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 519892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 519992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 520092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 520192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 520292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 520392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 520492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 520592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 52065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 520892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 520992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 521092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 521192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 521292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 521392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 521492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 521592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 521692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 521792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 521892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 521992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 522092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 522192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 522292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_TYPE = 1; 522392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 522492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 522592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 522692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 522792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 522892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 52295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 52305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 52315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 52325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 523392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 523492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 52355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 52365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 52375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 52405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 52415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 52425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 52445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 52455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 52465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 52475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 52485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 52495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 52505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 52515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 52525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 52535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 525492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 525592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 525692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 52575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 52585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 52595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 52605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 52645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 52655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 52685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 527092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 527192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 527292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 527392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 527492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 527592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 527692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 527792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 527892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 527992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 528092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 5281ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 5282ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(db, rawContactId); 5283ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 5284ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 52855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 52865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 52875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 52885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 52895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 52905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 52925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 52935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 52955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 52965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 52985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 52995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 53005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 53015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 53025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 53035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 53045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 53055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 53065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 53075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 53095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 53105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 53145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 53155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 53165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 53175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 53195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 5320763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 5321763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 53222f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false, false); 53232f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 53242f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 53252f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 53262f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * @param forStrequentFrequent Should be used only in strequent handling. 53272f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * true when this is for frequently contacted listing (not starred) 53282f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * @param strequentPhoneCallOnly Should be used only in strequent handling. 53292f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * true when this is for phone-only results. See also 53302f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * {@link ContactsContract#STREQUENT_PHONE_ONLY}. 53312f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 53322f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 53332f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] projection, boolean forStrequentFrequent, boolean strequentPhoneCallOnly) { 533482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5335ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 53362f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 53372f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Just for frequently contacted contacts in Strequent Uri handling. 53382f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (forStrequentFrequent) { 53392f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String strequentPhoneCallOnlyClause = 53402f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa (strequentPhoneCallOnly ? DbQueryUtils.concatenateClauses( 53412f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa MimetypesColumns.MIMETYPE + "=\'" + Phone.CONTENT_ITEM_TYPE + "'", 53422f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" + 53432f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_CALL) 53442f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa : ""); 53452f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Use INNER JOIN for maximum performance, ommiting unnecessary rows as much as 53462f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // possible. 53472f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa sb.append(" INNER JOIN " + 5348ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA_USAGE_STAT + " AS " + Tables.DATA_USAGE_STAT + 53492f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa " ON (" + 53502f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DbQueryUtils.concatenateClauses( 53512f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DataUsageStatColumns.CONCRETE_TIMES_USED + " > 0", 5352ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann RawContacts.CONTACT_ID + "=" + Views.CONTACTS + "." + Contacts._ID, 53532f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa strequentPhoneCallOnlyClause) + 53542f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa ")"); 53552f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 53562f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 53577ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 53587ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 5359916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 5360916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 5361916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5362916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5363916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 5364916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 5365916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 5366916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 5367916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 53687ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov String[] projection, String filter, long directoryId) { 53697ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov 53707ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5371ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 5372916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 537303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (filter != null) { 537403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov filter = filter.trim(); 537503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 537603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 537730cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov if (TextUtils.isEmpty(filter) || (directoryId != -1 && directoryId != Directory.DEFAULT)) { 537830cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov sb.append(" JOIN (SELECT NULL AS " + SearchSnippetColumns.SNIPPET + " WHERE 0)"); 53795e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } else { 53805e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov appendSearchIndexJoin(sb, uri, projection, filter); 53815e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 53827ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 53837ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 538403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setTables(sb.toString()); 538503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 538603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 5387916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 538803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private void appendSearchIndexJoin( 538903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov StringBuilder sb, Uri uri, String[] projection, String filter) { 5390916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5391174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET)) { 539203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String[] args = null; 539303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String snippetArgs = 539403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 539503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (snippetArgs != null) { 539603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov args = snippetArgs.split(","); 539703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 539803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 53995e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String startMatch = args != null && args.length > 0 ? args[0] 54005e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_START_MATCH; 54015e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String endMatch = args != null && args.length > 1 ? args[1] 54025e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_END_MATCH; 54035e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String ellipsis = args != null && args.length > 2 ? args[2] 54045e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_ELLIPSIS; 54055e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 54065e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 54075e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 5408174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov appendSearchIndexJoin( 5409174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov sb, filter, true, startMatch, endMatch, ellipsis, maxTokens); 5410174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 5411174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov appendSearchIndexJoin(sb, filter, false, null, null, null, 0); 5412174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 5413174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 5414174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 5415174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov public void appendSearchIndexJoin(StringBuilder sb, String filter, 5416174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean snippetNeeded, String startMatch, String endMatch, String ellipsis, 5417174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov int maxTokens) { 5418174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isEmailAddress = false; 5419174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String emailAddress = null; 5420174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isPhoneNumber = false; 5421174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String phoneNumber = null; 5422174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String numberE164 = null; 5423174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 54243716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // If the query consists of a single word, we can do snippetizing after-the-fact for a 54253716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // performance boost. 54263716f1447ceb21180d1301790eabd8b9453f486dDave Santoro boolean singleTokenSearch = filter.split(QUERY_TOKENIZER_REGEX).length == 1; 54273716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 5428174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (filter.indexOf('@') != -1) { 5429174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov emailAddress = mDbHelper.extractAddressFromEmailAddress(filter); 5430174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isEmailAddress = !TextUtils.isEmpty(emailAddress); 5431174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 5432174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isPhoneNumber = isPhoneNumber(filter); 543304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (isPhoneNumber) { 543404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann phoneNumber = PhoneNumberUtils.normalizeNumber(filter); 543504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann numberE164 = PhoneNumberUtils.formatNumberToE164(phoneNumber, 543604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann mDbHelper.getCountryIso()); 543704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 5438174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 5439174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 5440174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov sb.append(" JOIN (SELECT " + SearchIndexColumns.CONTACT_ID + " AS snippet_contact_id"); 5441174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (snippetNeeded) { 54425e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(", "); 54435e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 54443d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 54455e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 544604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Email.ADDRESS + ")"); 544704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS); 544804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 544904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID + " AND " + Email.ADDRESS + " LIKE "); 545004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann DatabaseUtils.appendEscapedSQLString(sb, filter + "%"); 545104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 54523d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 54533d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(","); 54543716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 54553716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Optimization for single-token search. 54563716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (singleTokenSearch) { 54573716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 54583716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 54593716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 54603716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 54613d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(")"); 54623d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 54633d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 54643d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 546504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Phone.NUMBER + ")"); 546604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + 546704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann Tables.DATA_JOIN_RAW_CONTACTS + " JOIN " + Tables.PHONE_LOOKUP); 546804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" ON " + DataColumns.CONCRETE_ID); 546904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + Tables.PHONE_LOOKUP + "." + PhoneLookupColumns.DATA_ID); 547004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 547104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID); 547204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" AND " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 547304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(phoneNumber); 547404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 547504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(numberE164)) { 547604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" OR " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 547704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(numberE164); 547804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 547904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 548004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 54815e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 54825e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 54833716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 54843716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Optimization for single-token search. 54853716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (singleTokenSearch) { 54863716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 54873716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 54883716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 54893716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 54905e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 549103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 549204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann final String normalizedFilter = NameNormalizer.normalize(filter); 549304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(normalizedFilter)) { 54943716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Optimization for single-token search. 54953716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (singleTokenSearch) { 54963716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 54973716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 54983716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("(CASE WHEN EXISTS (SELECT 1 FROM "); 54993716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.RAW_CONTACTS + " AS rc INNER JOIN "); 55003716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.NAME_LOOKUP + " AS nl ON (rc." + RawContacts._ID); 55013716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=nl." + NameLookupColumns.RAW_CONTACT_ID); 55023716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") WHERE nl." + NameLookupColumns.NORMALIZED_NAME); 55033716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" GLOB '" + normalizedFilter + "*' AND "); 55043716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("nl." + NameLookupColumns.NAME_TYPE + "="); 55053716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(NameLookupType.NAME_COLLATION_KEY + " AND "); 55063716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 55073716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=rc." + RawContacts.CONTACT_ID); 55083716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") THEN NULL ELSE "); 55093716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 55103716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" END)"); 55113716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 551204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } else { 551304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("NULL"); 551404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 551503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 55165e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" AS " + SearchSnippetColumns.SNIPPET); 55175e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 551803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 55195e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" FROM " + Tables.SEARCH_INDEX); 55205e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" WHERE "); 55215e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(Tables.SEARCH_INDEX + " MATCH "); 55225e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 55232352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, "\"" + sanitizeMatch(filter) + "*\""); 55243d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 55252352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, 552604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann "\"" + sanitizeMatch(filter) + "*\" OR \"" + phoneNumber + "*\"" 55272352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov + (numberE164 != null ? " OR \"" + numberE164 + "\"" : "")); 552803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 55292352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filter) + "*"); 55309c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 553103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(") ON (" + Contacts._ID + "=snippet_contact_id)"); 5532a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov } 5533a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov 55342352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov private String sanitizeMatch(String filter) { 55352352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov // TODO more robust preprocessing of match expressions 55362352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov return filter.replace('-', ' ').replace('\"', ' '); 55372352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov } 55382352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov 55395e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov private void appendSnippetFunction( 55405e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov StringBuilder sb, String startMatch, String endMatch, String ellipsis, int maxTokens) { 55415e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append("snippet(" + Tables.SEARCH_INDEX + ","); 55425e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 55435e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 55445e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 55455e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 55465e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, ellipsis); 55475e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 55485e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov // The index of the column used for the snippet, "content" 55495e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(",1,"); 55505e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(maxTokens); 55515e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 55525e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 55535e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 5554763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 5555763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 5556ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.RAW_CONTACTS); 5557763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 5558763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 5559763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 5560763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5561763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 5562a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForRawEntities(SQLiteQueryBuilder qb, Uri uri) { 5563ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.RAW_ENTITIES); 5564a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sRawEntityProjectionMap); 556546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 556646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 556746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 556882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 556982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 557046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, distinct, null); 557146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 557246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 557346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 557446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @param usageType when non-null {@link Tables#DATA_USAGE_STAT} is joined with the specified 557546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type. 557646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 557746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 557846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String[] projection, boolean distinct, Integer usageType) { 557982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5580ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 558182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 558282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 5583a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, RawContacts.CONTACT_ID); 5584a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 5585a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 5586a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 55873296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 558846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (usageType != null) { 558946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa appendDataUsageStatJoin(sb, usageType, DataColumns.CONCRETE_ID); 559046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 559146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 559282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 5593f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 5594f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov boolean useDistinct = distinct 5595f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov || !mDbHelper.isInProjection(projection, DISTINCT_DATA_PROHIBITING_COLUMNS); 5596f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setDistinct(useDistinct); 5597f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setProjectionMap(useDistinct ? sDistinctDataProjectionMap : sDataProjectionMap); 559882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 5599ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 5600ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 56010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 56020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 56030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5604ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 56050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 5606a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 5607a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 56080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 5609a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 5610a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 5611a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5612a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 56133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItems(SQLiteQueryBuilder qb) { 56143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StringBuilder sb = new StringBuilder(); 56153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann sb.append(Tables.STREAM_ITEMS).append(" JOIN ").append(Tables.RAW_CONTACTS) 56163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .append(" ON ").append(StreamItemsColumns.CONCRETE_RAW_CONTACT_ID).append("=") 56173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .append(RawContactsColumns.CONCRETE_ID) 56183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .append(" JOIN ").append(Tables.CONTACTS) 56193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .append(" ON ").append(RawContactsColumns.CONCRETE_CONTACT_ID).append("=") 56203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .append(ContactsColumns.CONCRETE_ID); 56213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setTables(sb.toString()); 56223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemsProjectionMap); 56233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 56243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 56253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItemPhotos(SQLiteQueryBuilder qb) { 56263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StringBuilder sb = new StringBuilder(); 56273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann sb.append(Tables.STREAM_ITEM_PHOTOS).append(" JOIN ").append(Tables.STREAM_ITEMS) 56283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .append(" ON ").append(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID).append("=") 56293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .append(StreamItemsColumns.CONCRETE_ID); 56303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setTables(sb.toString()); 56313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemPhotosProjectionMap); 56323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 56333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 5634a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForEntities(SQLiteQueryBuilder qb, Uri uri, 5635a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection) { 5636a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5637ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.ENTITIES); 5638a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" data"); 5639a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5640a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts.Entity.CONTACT_ID); 5641a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 5642a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, Contacts.Entity.DATA_ID); 5643a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, Contacts.Entity.DATA_ID); 5644a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5645a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 5646a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sEntityProjectionMap); 5647a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendAccountFromParameter(qb, uri); 5648a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5649a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5650a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactStatusUpdateJoin(StringBuilder sb, String[] projection, 5651a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lastStatusUpdateIdColumn) { 5652a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 5653a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS, 5654a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 5655a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 5656a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 5657a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 5658a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 5659a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 5660a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + lastStatusUpdateIdColumn + "=" 5661a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 56620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 5663a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 56640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 5665a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataStatusUpdateJoin(StringBuilder sb, String[] projection, 5666a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 5667b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 56680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 56690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 56700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 56710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 56720a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 56730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 5674a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 5675a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + dataIdColumn + ")"); 56760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 5677a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5678a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 567946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void appendDataUsageStatJoin(StringBuilder sb, int usageType, String dataIdColumn) { 568046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" LEFT OUTER JOIN " + Tables.DATA_USAGE_STAT + 568146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" + dataIdColumn + 568246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " AND " + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" + usageType + ")"); 568346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 568446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 5685a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactPresenceJoin(StringBuilder sb, String[] projection, 5686a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn) { 5687a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 5688a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_PRESENCE, Contacts.CONTACT_CHAT_CAPABILITY)) { 5689a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 5690a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + contactIdColumn + " = " 5691a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + ")"); 5692a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5693a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5694a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5695a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataPresenceJoin(StringBuilder sb, String[] projection, 5696a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 5697a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.PRESENCE, Data.CHAT_CAPABILITY)) { 5698a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 5699a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdates.DATA_ID + "=" + dataIdColumn + ")"); 5700a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5701a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5702a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 570324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private boolean appendLocalDirectorySelectionIfNeeded(SQLiteQueryBuilder qb, long directoryId) { 5704385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directoryId == Directory.DEFAULT) { 5705385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " IN " + Tables.DEFAULT_DIRECTORY); 570624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 5707385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directoryId == Directory.LOCAL_INVISIBLE){ 5708385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " NOT IN " + Tables.DEFAULT_DIRECTORY); 570924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 571024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 571124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return false; 571224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 571324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 571424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private void appendProfileRestriction(SQLiteQueryBuilder qb, Uri uri, String profileColumn, 571524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro boolean andRequired) { 571624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!shouldIncludeProfile(uri)) { 571724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.appendWhere((andRequired ? " AND (" : "") 571824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro + profileColumn + " IS NULL OR " 571924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro + profileColumn + "=0" 572024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro + (andRequired ? ")" : "")); 5721385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } 5722385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } 5723385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov 572424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private String prependProfileSortIfNeeded(Uri uri, String sortOrder) { 572524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (shouldIncludeProfile(uri)) { 572624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (TextUtils.isEmpty(sortOrder)) { 572724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return Contacts.IS_USER_PROFILE + " DESC"; 572824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } else { 572924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return Contacts.IS_USER_PROFILE + " DESC, " + sortOrder; 573024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 573124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 573224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return sortOrder; 573324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 573424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 573524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private boolean shouldIncludeProfile(Uri uri) { 573624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // The user's profile may be returned alongside other contacts if it was requested and 573724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // the calling application has permission to read profile data. 5738377850d2dfd28eaf1b22273a50cfe066f6667ab9Dave Santoro boolean profileRequested = readBooleanQueryParameter(uri, ContactsContract.ALLOW_PROFILE, 573924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro false); 574024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (profileRequested) { 574124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermission(false); 574224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 574324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return profileRequested; 574424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 574524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 57464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 5747f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 5748f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 5749e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5750e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 5751e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 5752e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 5753fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 5754fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 5755e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 5756e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5757e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 5758e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 5759e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 5760e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 57614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 57624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 57634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 57644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 57654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 57664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 57674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 57684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 57694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5770e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 5771f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 5772f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 5773e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5774e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 5775e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 5776e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 5777fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 5778fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 5779e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 5780e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5781e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 5782e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 5783e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 5784e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 5785e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 5786e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 5787e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 5788e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 5789e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 5790e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 5791e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 5792e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 5793e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5794e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 5795e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 5796e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 5797e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5798e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5799e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 58007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 5801c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 5802c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 5803c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 5804c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 5805c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 5806f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 58072e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limitParam = getQueryParameter(uri, ContactsContract.LIMIT_PARAM_KEY); 5808c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 5809c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5810c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5811c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 5812c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 5813c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 5814c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 5815c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 5816c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5817c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5818c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 5819c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 5820c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 5821c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5822c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5823c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5824c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 5825b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 5826f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 5827415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 5828415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov waitForAccess(mReadAccessLatch); 5829415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 5830b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 5831b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 5832a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 583324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 583424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForRawContact(rawContactId, false); 5835f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return openPhotoAssetFile(uri, mode, 583624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Data._ID + "=" + Contacts.PHOTO_ID + " AND " + 583724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro RawContacts.CONTACT_ID + "=?", 583824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro new String[]{String.valueOf(rawContactId)}); 5839e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5840b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5841e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 584224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long dataId = Long.parseLong(uri.getPathSegments().get(1)); 584324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForData(dataId, false); 5844f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return openPhotoAssetFile(uri, mode, 5845e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=? AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'", 584624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro new String[]{String.valueOf(dataId)}); 5847d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5848d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5849fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case PROFILE_AS_VCARD: { 5850fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // When opening a contact as file, we pass back contents as a 5851fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // vCard-encoded stream. We build into a local buffer first, 5852fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // then pipe into MemoryFile once the exact size is known. 5853fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 5854fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 5855fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen return buildAssetFileDescriptor(localStream); 5856fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen } 585742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 5858fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case CONTACTS_AS_VCARD: { 585942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 586042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 586142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 586242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 5863fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 5864f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 586542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 586642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 586742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 586849d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 586942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 587042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 587142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 5872fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Uri queryUri = Contacts.CONTENT_URI; 587342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 5874fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen 5875fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen mProfileIdCache.init(mDb, false); 5876fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen 5877d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 5878d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 587942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 588042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 5881d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 588242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 5883d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 588442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 588524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long contactId = lookupContactIdByLookupKey(db, lookupKey); 588624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceProfilePermissionForContact(contactId, false); 588724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro inBuilder.append(contactId); 5888fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if (mProfileIdCache.profileContactId == contactId) { 5889fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen queryUri = queryUri.buildUpon().appendQueryParameter( 5890377850d2dfd28eaf1b22273a50cfe066f6667ab9Dave Santoro ContactsContract.ALLOW_PROFILE, "true").build(); 5891fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen } 589242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 589342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 589442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 589542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 5896d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5897d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 5898d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 5899d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 5900d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 5901fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(queryUri, localStream, selection, null); 5902f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 5903d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5904b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5905b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 5906fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("File does not exist", 5907fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov uri)); 5908b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5909b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5910b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5911f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor openPhotoAssetFile(Uri uri, String mode, String selection, 5912e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String[] selectionArgs) 5913e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 5914e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 5915e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("Mode " + mode 5916e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 5917e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5918e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 5919e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 5920ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann "SELECT " + Photo.PHOTO + " FROM " + Views.DATA + 5921e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 5922e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 592308ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood try { 5924f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 5925f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert DatabaseUtils.blobFileDescriptorForQuery(db, sql, selectionArgs)); 592608ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } catch (SQLiteDoneException e) { 592708ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood // this will happen if the DB query returns no rows (i.e. contact does not exist) 592808ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood throw new FileNotFoundException(uri.toString()); 592908ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } 5930e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5931e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 5932d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 5933d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5934d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5935f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert * Returns an {@link AssetFileDescriptor} backed by the 5936d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 5937d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5938f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 5939d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 5940d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 5941d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5942d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 5943d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5944f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 5945f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert ParcelFileDescriptor.fromData(byteData, CONTACT_MEMORY_FILE_NAME), 5946f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert byteData.length); 5947d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 5948ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert Log.w(TAG, "Problem writing stream into an ParcelFileDescriptor: " + e.toString()); 5949ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return null; 5950d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5951d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5952d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5953f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd) { 5954f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor(fd, AssetFileDescriptor.UNKNOWN_LENGTH); 5955f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 5956f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 5957f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd, long length) { 5958f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return fd != null ? new AssetFileDescriptor(fd, 0, length) : null; 5959f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 5960f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 5961d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5962d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 5963d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 5964d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 5965d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5966fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen private void outputRawContactsAsVCard(Uri uri, OutputStream stream, 5967fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen String selection, String[] selectionArgs) { 5968d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 5969dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen int vcardconfig = VCardConfig.VCARD_TYPE_DEFAULT; 5970fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if(uri.getBooleanQueryParameter( 5971fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, false)) { 5972dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen vcardconfig |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT; 5973dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen } 59747a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 5975dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen new VCardComposer(context, vcardconfig, false); 5976108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Writer writer = null; 5977108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 5978108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer = new BufferedWriter(new OutputStreamWriter(stream)); 5979fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if (!composer.init(uri, selection, selectionArgs, null)) { 5980108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 5981108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return; 5982108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 5983d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5984108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa while (!composer.isAfterLast()) { 5985108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.write(composer.createOneEntry()); 5986108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 5987108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 5988108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.e(TAG, "IOException: " + e); 5989108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } finally { 5990108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa composer.terminate(); 5991108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa if (writer != null) { 5992108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 5993108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.close(); 5994108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 5995108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "IOException during closing output stream: " + e); 5996108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 5997d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5998d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5999d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 6000b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 60014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 60024f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 6003415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 6004415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov waitForAccess(mReadAccessLatch); 6005415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 6006a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 60074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 6008b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 6009be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 60102d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 6011b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 6012b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 601324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 6014b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 6015f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 601642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 601724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 6018f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 6019f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov case CONTACTS_ID_PHOTO: 6020f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov return "image/png"; 6021b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 602224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 6023be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 6024b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 602524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 6026b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 6027f481f22a9323fe338672f99b88b26c5f0725cd42David Brown case DATA: 602824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 6029f481f22a9323fe338672f99b88b26c5f0725cd42David Brown return Data.CONTENT_TYPE; 6030508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 6031b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 603248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 603348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 603448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 603548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 60369005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 60379005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 603848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 603948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 604048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 604148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 604248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 604348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 604448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 604548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 6046b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 6047b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 6048b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 6049b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 6050b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 6051b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 6052b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 6053b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 6054c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 6055c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 6056c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 6057c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 6058d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES: 6059d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_TYPE; 6060d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID: 6061d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_ITEM_TYPE; 606261efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 606361efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 60644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 60654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 60667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 606709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public String[] getDefaultProjection(Uri uri) { 606809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov final int match = sUriMatcher.match(uri); 606909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov switch (match) { 607009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS: 607109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP: 607209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_ID: 607309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP_ID: 607409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 607524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 607609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsProjectionMap.getColumnNames(); 607709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 60788727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov case CONTACTS_ID_ENTITIES: 607924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: 60808727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov return sEntityProjectionMap.getColumnNames(); 60818727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov 608209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_VCARD: 608309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_MULTI_VCARD: 608424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 608509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsVCardProjectionMap.getColumnNames(); 608609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 608709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS: 608809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS_ID: 608924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 609024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 609109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sRawContactsProjectionMap.getColumnNames(); 609209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 609309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DATA_ID: 609409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES: 609509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES_ID: 609609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS: 609709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS_ID: 609809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS: 609909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS_ID: 610024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 610109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDataProjectionMap.getColumnNames(); 610209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 610309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONE_LOOKUP: 610409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sPhoneLookupProjectionMap.getColumnNames(); 610509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 610609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 610709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 610809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sAggregationExceptionsProjectionMap.getColumnNames(); 610909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 611009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case SETTINGS: 611109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sSettingsProjectionMap.getColumnNames(); 611209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 611309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES: 611409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES_ID: 611509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDirectoryProjectionMap.getColumnNames(); 611609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 611709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov default: 611809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return null; 611909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 612009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 612109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 6122f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 6123f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6124f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 6125f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 6126f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6127f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6128f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 6129f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 6130f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 613178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mDbHelper.insertNameLookup(rawContactId, dataId, lookupType, name); 6132f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6133f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 6134f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 6135f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 6136d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 6137f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6138f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 6139f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 61402d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 6141d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 6142d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 6143d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 6144d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 6145d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 6146d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 6147d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 6148e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 6149916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 6150916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 6151e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 6152e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 61539a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov public boolean isPhoneNumber(String filter) { 61549a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean atLeastOneDigit = false; 61559a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov int len = filter.length(); 61569a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov for (int i = 0; i < len; i++) { 61579a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov char c = filter.charAt(i); 61589a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (c >= '0' && c <= '9') { 61599a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov atLeastOneDigit = true; 61609a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } else if (c != '*' && c != '#' && c != '+' && c != 'N' && c != '.' && c != ';' 61619a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov && c != '-' && c != '(' && c != ')' && c != ' ') { 61629a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 61639a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 61649a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 61659a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return atLeastOneDigit; 61669a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 61679a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 61684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 61697a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * Takes components of a name from the query parameters and returns a cursor with those 61707a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * components as well as all missing components. There is no database activity involved 61717a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * in this so the call can be made on the UI thread. 61727a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov */ 61737a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private Cursor completeName(Uri uri, String[] projection) { 61747a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (projection == null) { 61757a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov projection = sDataProjectionMap.getColumnNames(); 61767a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 61777a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 61787a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ContentValues values = new ContentValues(); 6179f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov DataRowHandlerForStructuredName handler = (DataRowHandlerForStructuredName) 6180f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov getDataRowHandler(StructuredName.CONTENT_ITEM_TYPE); 61817a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 61827a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov copyQueryParamsToContentValues(values, uri, 61837a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.DISPLAY_NAME, 61847a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PREFIX, 61857a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.GIVEN_NAME, 61867a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.MIDDLE_NAME, 61877a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.FAMILY_NAME, 61887a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.SUFFIX, 61897a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_NAME, 61907a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_FAMILY_NAME, 61917a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_MIDDLE_NAME, 61927a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_GIVEN_NAME 61937a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ); 61947a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 61957a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov handler.fixStructuredNameComponents(values, values); 61967a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 61977a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 61987a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov Object[] row = new Object[projection.length]; 61997a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (int i = 0; i < projection.length; i++) { 62007a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov row[i] = values.get(projection[i]); 62017a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62027a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.addRow(row); 62037a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return cursor; 62047a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62057a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 62067a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private void copyQueryParamsToContentValues(ContentValues values, Uri uri, String... columns) { 62077a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (String column : columns) { 62087a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String param = uri.getQueryParameter(column); 62097a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (param != null) { 62107a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov values.put(column, param); 62117a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62127a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62137a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 62147a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 62157a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 62167a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov /** 62174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 62184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 62194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 6220b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 6221b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 6222b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 6223b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 6224b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 62254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 62264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 6227b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 6228b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 6229b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 6230caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 62315e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 62325e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 62335e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 62345e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 62355e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 62365e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 62375e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 62385e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 62395e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 62405e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 62415e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 6242caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 6243caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 6244caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 62455f1f4a062ac34d75d2dbf586702cbeb121cf09caDmitri Plotnikov Account[] accounts = accountManager.getAccountsByType(DEFAULT_ACCOUNT_TYPE); 6246caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 6247caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 6248caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 6249caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 62506f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 6251caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 62526f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 6253caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 6254f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 625573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 625673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov * Returns true if the specified account type is writable. 625773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 625873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov protected boolean isWritableAccount(String accountType) { 6259bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov if (accountType == null) { 6260bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 6261bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 6262bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 626373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov Boolean writable = mAccountWritability.get(accountType); 626473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 626573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 626673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 626773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 6268627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 6269627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 6270627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 6271627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 627273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov accountType.equals(sync.accountType)) { 627373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 627473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 6275627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 6276627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 6277627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 6278627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 6279627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 628073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 628173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 628273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 628373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 628473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 628573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.put(accountType, writable); 628673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 6287627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 6288b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 6289d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 6290f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 6291f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 6292f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6293f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 6294f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 6295f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 6296f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 6297f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6298f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6299f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 6300f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 6301f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 6302f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6303f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6304f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 6305f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6306f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 6307f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 6308f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6309f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6310f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 6311f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 6312f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 6313f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 6314f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 6315f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6316f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6317f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 6318f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 6319f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 6320f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 6321f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 6322f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 6323f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 6324f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6325f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6326f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 6327f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 6328f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6329f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 6330f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 6331f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 6332f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 6333f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 6334f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 63355fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 63365fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa 63375fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // Should match against the whole parameter instead of its suffix. 63385fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // e.g. The parameter "param" must not be found in "some_param=val". 63395fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (index > 0) { 63405fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa char prevChar = query.charAt(index - 1); 63415fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (prevChar != '?' && prevChar != '&') { 63425fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // With "some_param=val1¶m=val2", we should find second "param" occurrence. 63435fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa index += parameterLength; 63445fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa continue; 63455fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 6346f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6347f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6348f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 6349f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6350f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 6351f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 6352f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6353f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6354f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 6355f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 6356f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 6357f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6358f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6359f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6360f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 6361f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 6362f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 6363f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 6364f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 6365f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6366f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6367f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 6368f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 63695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 63700dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov protected boolean isAggregationUpgradeNeeded() { 63710dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 63720dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return false; 63730dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 63740dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 63750dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_AGGREGATION_ALGORITHM, "1")); 63760dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return version < PROPERTY_AGGREGATION_ALGORITHM_VERSION; 63770dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 63780dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 6379bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void upgradeAggregationAlgorithmInBackground() { 63800dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // This upgrade will affect very few contacts, so it can be performed on the 63810dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // main thread during the initial boot after an OTA 63820dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 63830dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Upgrading aggregation algorithm"); 63840dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int count = 0; 63850dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 63860dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 638749d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 63880dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDb.beginTransaction(); 63890dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Cursor cursor = mDb.query(true, 63900dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Tables.RAW_CONTACTS + " r1 JOIN " + Tables.RAW_CONTACTS + " r2", 63910dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov new String[]{"r1." + RawContacts._ID}, 63920dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov "r1." + RawContacts._ID + "!=r2." + RawContacts._ID + 63930dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.CONTACT_ID + "=r2." + RawContacts.CONTACT_ID + 63940dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_NAME + "=r2." + RawContacts.ACCOUNT_NAME + 63950dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_TYPE + "=r2." + RawContacts.ACCOUNT_TYPE, 63960dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov null, null, null, null, null); 63970dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 63980dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov while (cursor.moveToNext()) { 63990dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long rawContactId = cursor.getLong(0); 64000dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, 64010dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 64020dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov count++; 64030dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 64040dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 64050dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov cursor.close(); 64060dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 6407bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mContactAggregator.aggregateInTransaction(mTransactionContext, mDb); 6408bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 64090dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDb.setTransactionSuccessful(); 64100dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDbHelper.setProperty(PROPERTY_AGGREGATION_ALGORITHM, 64110dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov String.valueOf(PROPERTY_AGGREGATION_ALGORITHM_VERSION)); 64120dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 64130dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mDb.endTransaction(); 64140dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 64150dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Aggregation algorithm upgraded for " + count 64160dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov + " contacts, in " + (end - start) + "ms"); 64170dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 64180dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 64199a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 64209a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov /* Visible for testing */ 64219a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean isPhone() { 64229a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (!sIsPhoneInitialized) { 64239a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhone = new TelephonyManager(getContext()).isVoiceCapable(); 64249a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhoneInitialized = true; 64259a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 64269a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return sIsPhone; 64279a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 642846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 642946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private boolean handleDataUsageFeedback(Uri uri) { 643046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final long currentTimeMillis = System.currentTimeMillis(); 643146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String usageType = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 643246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] ids = uri.getLastPathSegment().trim().split(","); 643346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ArrayList<Long> dataIds = new ArrayList<Long>(); 643446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 643546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (String id : ids) { 643646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa dataIds.add(Long.valueOf(id)); 643746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 643846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final boolean successful; 643946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (TextUtils.isEmpty(usageType)) { 644046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.w(TAG, "Method for data usage feedback isn't specified. Ignoring."); 644146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = false; 644246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 644346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = updateDataUsageStat(dataIds, usageType, currentTimeMillis) > 0; 644446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 644546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 644646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Handle old API. This doesn't affect the result of this entire method. 644746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] questionMarks = new String[ids.length]; 644846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Arrays.fill(questionMarks, "?"); 644946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = Data._ID + " IN (" + TextUtils.join(",", questionMarks) + ")"; 645046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final Cursor cursor = mDb.query( 6451ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA, 645246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { Data.CONTACT_ID }, 645346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa where, ids, null, null, null); 645446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 645546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa while (cursor.moveToNext()) { 645646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mSelectionArgs1[0] = cursor.getString(0); 645746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa ContentValues values2 = new ContentValues(); 645846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values2.put(Contacts.LAST_TIME_CONTACTED, currentTimeMillis); 645946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mDb.update(Tables.CONTACTS, values2, Contacts._ID + "=?", mSelectionArgs1); 646046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 646146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 646246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 646346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 646446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 646546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 646646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 646746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return successful; 646846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 646946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 647046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 647146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Update {@link Tables#DATA_USAGE_STAT}. 647246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * 647346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @return the number of rows affected. 647446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 647546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private int updateDataUsageStat( 647646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa ArrayList<Long> dataIds, String type, long currentTimeMillis) { 647746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final int typeInt = sDataUsageTypeMap.get(type); 647846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = DataUsageStatColumns.DATA_ID + " =? AND " 647946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT + " =?"; 648046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] columns = 648146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { DataUsageStatColumns._ID, DataUsageStatColumns.TIMES_USED }; 648246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ContentValues values = new ContentValues(); 648346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (Long dataId : dataIds) { 648446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] args = new String[] { dataId.toString(), String.valueOf(typeInt) }; 648546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mDb.beginTransaction(); 648646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 648746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final Cursor cursor = mDb.query(Tables.DATA_USAGE_STAT, columns, where, args, 648846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa null, null, null); 648946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 649046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (cursor.getCount() > 0) { 649146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!cursor.moveToFirst()) { 649246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.e(TAG, 649346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa "moveToFirst() failed while getAccount() returned non-zero."); 649446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 649546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 649646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, cursor.getInt(1) + 1); 649746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 649846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mDb.update(Tables.DATA_USAGE_STAT, values, 649946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns._ID + " =?", 650046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { cursor.getString(0) }); 650146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 650246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 650346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 650446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.DATA_ID, dataId); 650546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.USAGE_TYPE_INT, typeInt); 650646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, 1); 650746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 650846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mDb.insert(Tables.DATA_USAGE_STAT, null, values); 650946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 651046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mDb.setTransactionSuccessful(); 651146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 651246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 651346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 651446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 651546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mDb.endTransaction(); 651646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 651746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 651846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 651946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return dataIds.size(); 652046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 652146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 652246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 652346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Returns a sort order String for promoting data rows (email addresses, phone numbers, etc.) 652446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * associated with a primary account. The primary account should be supplied from applications 652546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * with {@link ContactsContract#PRIMARY_ACCOUNT_NAME} and 652646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * {@link ContactsContract#PRIMARY_ACCOUNT_TYPE}. Null will be returned when the primary 652746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * account isn't available. 652846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 652946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private String getAccountPromotionSortOrder(Uri uri) { 653046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountName = 653146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_NAME); 653246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountType = 653346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_TYPE); 653446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 653546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Data rows associated with primary account should be promoted. 653646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountName)) { 653746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa StringBuilder sb = new StringBuilder(); 653846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append("(CASE WHEN " + RawContacts.ACCOUNT_NAME + "="); 653946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountName); 654046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountType)) { 654146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" AND " + RawContacts.ACCOUNT_TYPE + "="); 654246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountType); 654346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 654446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" THEN 0 ELSE 1 END)"); 654546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return sb.toString(); 654646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 654746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return null; 654846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 654946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 65504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 6551