ContactsProvider2.java revision 8ead0dc62d0031a22af0d14c7ed05893507893c9
14f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/* 24f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Copyright (C) 2009 The Android Open Source Project 34f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 44f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 54f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * you may not use this file except in compliance with the License. 64f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * You may obtain a copy of the License at 74f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 84f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 94f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Unless required by applicable law or agreed to in writing, software 114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * See the License for the specific language governing permissions and 144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * limitations under the License 154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts; 1828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar 1953214b3ed12b0ff9cb589b6559311f2ac142f2e3Bjorn Bringertimport com.android.common.content.SyncStateContentProviderHelper; 205b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport com.android.providers.contacts.ContactAggregator.AggregationSuggestionParameter; 2197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 2297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 2397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 2497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 2597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 2697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 2797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 2871340347b4862d4b1368a5d69d1667e2245952e4Daisuke Miyakawaimport com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns; 2997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 3023ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onukiimport com.android.providers.contacts.ContactsDatabaseHelper.Joins; 312f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawaimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 3297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 3397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 3497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 3597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 361dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoroimport com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns; 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.StreamItemPhotosColumns; 43f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport com.android.providers.contacts.ContactsDatabaseHelper.StreamItemsColumns; 4497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 45ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmannimport com.android.providers.contacts.ContactsDatabaseHelper.Views; 46d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmannimport com.android.providers.contacts.SearchIndexManager.FtsQueryBuilder; 472f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawaimport com.android.providers.contacts.util.DbQueryUtils; 4897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.vcard.VCardComposer; 4997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.vcard.VCardConfig; 5097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Lists; 5197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Maps; 5297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Sets; 53f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawaimport com.google.common.annotations.VisibleForTesting; 5497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 55b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 56caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 575b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 58bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.Notification; 59bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.NotificationManager; 60bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.PendingIntent; 61c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 62568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 63568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 646ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 6535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 6667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 6767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 68627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.IContentService; 69bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.content.Intent; 70568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 713d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 72627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 7367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 740bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmannimport android.content.pm.PackageManager; 750bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmannimport android.content.pm.PackageManager.NameNotFoundException; 765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoroimport android.content.pm.ProviderInfo; 77f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringertimport android.content.res.AssetFileDescriptor; 783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport android.content.res.Resources; 790bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmannimport android.content.res.Resources.NotFoundException; 80409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onukiimport android.database.AbstractCursor; 81e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikovimport android.database.CrossProcessCursor; 824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 83e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikovimport android.database.CursorWindow; 84ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.CursorWrapper; 85ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 8609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor; 8709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor.RowBuilder; 884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 8908ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwoodimport android.database.sqlite.SQLiteDoneException; 904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 91f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.graphics.Bitmap; 92f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.graphics.BitmapFactory; 934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 94d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.net.Uri.Builder; 95c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoroimport android.os.AsyncTask; 96bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Binder; 976ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 98bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Handler; 99bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.HandlerThread; 100bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Message; 101ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringertimport android.os.ParcelFileDescriptor; 102c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoroimport android.os.ParcelFileDescriptor.AutoCloseInputStream; 103bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Process; 104b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 10515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikovimport android.os.StrictMode; 1060dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikovimport android.os.SystemClock; 1070e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 1083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 109508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 1103de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 111b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 11282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoroimport android.provider.ContactsContract.Authorization; 11397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 11497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 11597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 11697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 1176d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Note; 11897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 11997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 12097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 1214928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.SipAddress; 12297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 12397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 124ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 1253de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 1265b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions; 1273de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 12871340347b4862d4b1368a5d69d1667e2245952e4Daisuke Miyakawaimport android.provider.ContactsContract.DataUsageFeedback; 129d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory; 130f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.provider.ContactsContract.DisplayPhoto; 1313de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 132bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.provider.ContactsContract.Intents; 1333de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 1341dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoroimport android.provider.ContactsContract.PhotoFiles; 1350c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoroimport android.provider.ContactsContract.Profile; 13609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 1373de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 1383711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenenimport android.provider.ContactsContract.RawContactsEntity; 139916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 1403de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 14182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 1423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport android.provider.ContactsContract.StreamItemPhotos; 143f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.provider.ContactsContract.StreamItems; 14497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.OpenableColumns; 14597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.SyncStateContract; 146a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 1479a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikovimport android.telephony.TelephonyManager; 148a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 149c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 151108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.BufferedWriter; 152d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 153f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport java.io.File; 154b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 155d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 156d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 157108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.OutputStreamWriter; 158108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.Writer; 159d0eb93009559d095de0448907527aeb059801dc4Dave Santoroimport java.security.SecureRandom; 16042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.text.SimpleDateFormat; 1617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 16246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawaimport java.util.Arrays; 1635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 16442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.util.Date; 165b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1660e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 168622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 169b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1700e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 171ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 177078f588cef389358adabc579de00747878f3c108Dave Santoropublic class ContactsProvider2 extends AbstractContactsProvider 178078f588cef389358adabc579de00747878f3c108Dave Santoro implements OnAccountsUpdateListener { 179caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 180bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 181bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 182bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 18415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_INITIALIZE = 0; 18515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_OPEN_WRITE_ACCESS = 1; 18615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS = 2; 18715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_ACCOUNTS = 3; 18815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_LOCALE = 4; 18915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM = 5; 19005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_SEARCH_INDEX = 6; 19105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_PROVIDER_STATUS = 7; 19205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_DIRECTORIES = 8; 19305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_CHANGE_LOCALE = 9; 194f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int BACKGROUND_TASK_CLEANUP_PHOTOS = 10; 195619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Limit for the maximum number of social stream items to store under a raw contact. */ 2003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int MAX_STREAM_ITEMS_PER_RAW_CONTACT = 5; 2013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 202f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** Rate limit (in ms) for photo cleanup. Do it at most once per day. */ 203f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int PHOTO_CLEANUP_RATE_LIMIT = 24 * 60 * 60 * 1000; 204f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 2053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 20682792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * Default expiration duration for pre-authorized URIs. May be overridden from a secure 20782792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * setting. 20882792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro */ 20982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro private static final int DEFAULT_PREAUTHORIZED_URI_EXPIRATION = 5 * 60 * 1000; 21082792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 21182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro /** 21282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * Random URI parameter that will be appended to preauthorized URIs for uniqueness. 21382792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro */ 21482792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro private static final String PREAUTHORIZED_URI_TOKEN = "perm_token"; 21582792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 21682792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro /** 217b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov * Property key for the legacy contact import version. The need for a version 2183d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 2193d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 2203d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 221b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final String PROPERTY_CONTACTS_IMPORTED = "contacts_imported_v1"; 222b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int PROPERTY_CONTACTS_IMPORT_VERSION = 1; 22351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final String PREF_LOCALE = "locale"; 2243d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2250dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final String PROPERTY_AGGREGATION_ALGORITHM = "aggregation_v2"; 2260dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final int PROPERTY_AGGREGATION_ALGORITHM_VERSION = 2; 2270dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 2280e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 2290e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 2305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final ProfileAwareUriMatcher sUriMatcher = 2315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ProfileAwareUriMatcher(UriMatcher.NO_MATCH); 2324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2332f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 2342f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * Used to insert a column into strequent results, which enables SQL to sort the list using 2352f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * the total times contacted. See also {@link #sStrequentFrequentProjectionMap}. 2362f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 2372f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private static final String TIMES_USED_SORT_COLUMN = "times_used_sort"; 2385e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 239d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 2402f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa + TIMES_USED_SORT_COLUMN + " DESC, " 2419b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 242d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 243d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 244d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 245d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 24645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa private static final String FREQUENT_ORDER_BY = DataUsageStatColumns.TIMES_USED + " DESC," 24745ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 24845ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa 2496e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 2509b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 2519b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 2529b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 2539b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 2546e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 2559b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 2569b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 2579b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 2589b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 259de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 260de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 2613716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Regex for splitting query strings - we split on any group of non-alphanumeric characters, 2623716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // excluding the @ symbol. 2633716f1447ceb21180d1301790eabd8b9453f486dDave Santoro /* package */ static final String QUERY_TOKENIZER_REGEX = "[^\\w@]+"; 2643716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 265d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 266d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 2675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 2685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 269a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_DATA = 1004; 2705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 2715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 2725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 2735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 274a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_PHOTO = 1009; 275bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_PHOTO = 1010; 276bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_PHOTO = 1011; 277bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_ID_DISPLAY_PHOTO = 1012; 278bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_DISPLAY_PHOTO = 1013; 279bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_DISPLAY_PHOTO = 1014; 280bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_AS_VCARD = 1015; 281bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_AS_MULTI_VCARD = 1016; 282bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_DATA = 1017; 283bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_DATA = 1018; 284bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_ID_ENTITIES = 1019; 285bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ENTITIES = 1020; 286bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_ENTITIES = 1021; 287bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_ID_STREAM_ITEMS = 1022; 288bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_STREAM_ITEMS = 1023; 289bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_STREAM_ITEMS = 1024; 290bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_FREQUENT = 1025; 2914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 2935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 2945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 29546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 296f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int RAW_CONTACTS_ID_DISPLAY_PHOTO = 2006; 297f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int RAW_CONTACTS_ID_STREAM_ITEMS = 2007; 29882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro private static final int RAW_CONTACTS_ID_STREAM_ITEMS_ID = 2008; 2994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 3006bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 3016bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 302ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 30348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 30448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 30548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 30648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 30748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 30848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 30948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 31048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 311a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 3136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 314b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 315b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 316b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 31782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 31882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 3191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 32031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 32131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 322eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 323eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 324ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 325ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 326ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 327ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 32835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 329b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 3305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_SYNCSTATE = 11002; 3315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_SYNCSTATE_ID = 11003; 33235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 333c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 334c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 335c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 33646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 33746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 33809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 33909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 340d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES = 17001; 341d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES_ID = 17002; 342d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3437a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private static final int COMPLETE_NAME = 18000; 3447a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 34524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE = 19000; 34624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_ENTITIES = 19001; 34724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA = 19002; 34824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA_ID = 19003; 34924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_AS_VCARD = 19004; 35024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS = 19005; 35124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID = 19006; 35224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_DATA = 19007; 35324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_ENTITIES = 19008; 3545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_STATUS_UPDATES = 19009; 3553202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro private static final int PROFILE_RAW_CONTACT_ENTITIES = 19010; 35685077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro private static final int PROFILE_PHOTO = 19011; 35785077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro private static final int PROFILE_DISPLAY_PHOTO = 19012; 35824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 35946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final int DATA_USAGE_FEEDBACK_ID = 20001; 36046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 3613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS = 21000; 3623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_PHOTOS = 21001; 3633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID = 21002; 3643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS = 21003; 3653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS_ID = 21004; 3663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_LIMIT = 21005; 3673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 368f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int DISPLAY_PHOTO = 22000; 369f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int PHOTO_DIMENSIONS = 22001; 370f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 3715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Inserts into URIs in this map will direct to the profile database if the parent record's 3725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // value (looked up from the ContentValues object with the key specified by the value in this 3735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // map) is in the profile ID-space (see {@link ProfileDatabaseHelper#PROFILE_ID_SPACE}). 3745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final Map<Integer, String> INSERT_URI_ID_VALUE_MAP = Maps.newHashMap(); 3755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro static { 3765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(DATA, Data.RAW_CONTACT_ID); 3775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(RAW_CONTACTS_DATA, Data.RAW_CONTACT_ID); 3785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STATUS_UPDATES, StatusUpdates.DATA_ID); 3795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS, StreamItems.RAW_CONTACT_ID); 3805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(RAW_CONTACTS_ID_STREAM_ITEMS, StreamItems.RAW_CONTACT_ID); 3815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID); 3825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS_ID_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID); 3835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 3845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 38536612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro // Any interactions that involve these URIs will also require the calling package to have either 38636612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro // android.permission.READ_SOCIAL_STREAM permission or android.permission.WRITE_SOCIAL_STREAM 38736612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro // permission, depending on the type of operation being performed. 38836612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro private static final List<Integer> SOCIAL_STREAM_URIS = Lists.newArrayList( 38936612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro CONTACTS_ID_STREAM_ITEMS, 39036612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro CONTACTS_LOOKUP_STREAM_ITEMS, 39136612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro CONTACTS_LOOKUP_ID_STREAM_ITEMS, 39236612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro RAW_CONTACTS_ID_STREAM_ITEMS, 39336612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro RAW_CONTACTS_ID_STREAM_ITEMS_ID, 39436612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro STREAM_ITEMS, 39536612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro STREAM_ITEMS_PHOTOS, 39636612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro STREAM_ITEMS_ID, 39736612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro STREAM_ITEMS_ID_PHOTOS, 39836612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro STREAM_ITEMS_ID_PHOTOS_ID 39936612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro ); 40036612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro 401dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID = 402dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 403dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME 404dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 405dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE 40643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + "=" + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND (" 40743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET 40843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + "=" + RawContactsColumns.CONCRETE_DATA_SET + " OR " 40943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 41043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL)" 411dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + " != 0"; 412dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 413dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID = 414dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 415dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 416dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 417dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 41843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND (" 41943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + "=" 42043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " OR " 42143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 42243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL)" 42343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + " AND " + Groups.AUTO_ADD + " != 0"; 424dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 425dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String[] PROJECTION_GROUP_ID 426dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana = new String[]{Tables.GROUPS + "." + Groups._ID}; 427dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 428dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_GROUPMEMBERSHIP_DATA = DataColumns.MIMETYPE_ID + "=? " 429dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.GROUP_ROW_ID + "=? " 430dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.RAW_CONTACT_ID + "=?"; 431dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 432dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_STARRED_FROM_RAW_CONTACTS = 433dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT " + RawContacts.STARRED 434dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?"; 435dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 436d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 437f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 438f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 439f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 44067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 44167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 4426cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 4436802030a777c0c3ba1dc029c534cca4784260632Dave Santoro RawContactsColumns.CONCRETE_ACCOUNT_TYPE, 4446802030a777c0c3ba1dc029c534cca4784260632Dave Santoro RawContactsColumns.CONCRETE_ACCOUNT_NAME, 44543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContactsColumns.CONCRETE_DATA_SET, 4463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 447f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 448ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 449ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 450d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 4516802030a777c0c3ba1dc029c534cca4784260632Dave Santoro public static final int ACCOUNT_TYPE = 1; 4526802030a777c0c3ba1dc029c534cca4784260632Dave Santoro public static final int ACCOUNT_NAME = 2; 45343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int DATA_SET = 3; 45443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int DATA_ID = 4; 45543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int CONTACT_ID = 5; 456ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4571f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 458f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov interface RawContactsQuery { 45919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 46019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 46119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 462ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 463ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 464ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 46543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.DATA_SET, 46619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 46719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 46819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 469ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 470ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 47143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int DATA_SET = 3; 47219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 47319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 474c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 475caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 47671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 47771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 47871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 47971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 48071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 48171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 48271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 48371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 4847cf50494501938f175d288077145acf49da8f171Daniel Lehmann + " WHERE " + DataColumns.MIMETYPE_ID + "=?" 4857cf50494501938f175d288077145acf49da8f171Daniel Lehmann + " AND " + GroupMembership.GROUP_ROW_ID + "=" 48671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 48771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 48871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 48971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 490a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 491a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 492a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 493a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 494a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 495a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 496a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 497a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 498a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 499a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 500a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 501a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 502c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Current contacts - those contacted within the last 3 days (in seconds) 503c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_CURRENT = 3 * 24 * 60 * 60; 504c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 505c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Recent contacts - those contacted within the last 30 days (in seconds) 506c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_RECENT = 30 * 24 * 60 * 60; 507c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 508f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa private static final String TIME_SINCE_LAST_USED = 509f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa "(strftime('%s', 'now') - " + DataUsageStatColumns.LAST_TIME_USED + "/1000)"; 510f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa 511c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov /* 512c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * Sorting order for email address suggestions: first starred, then the rest. 5132262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * second in_visible_group, then the rest. 5142262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * Within the four (starred/unstarred, in_visible_group/not-in_visible_group) groups 5152262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * - three buckets: very recently contacted, then fairly 516c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * recently contacted, then the rest. Within each of the bucket - descending count 51746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * of times contacted (both for data row and for contact row). If all else fails, alphabetical. 51846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * (Super)primary email address is returned before other addresses for the same contact. 519c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov */ 520c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final String EMAIL_FILTER_SORT_ORDER = 5212262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa Contacts.STARRED + " DESC, " 5222262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa + Contacts.IN_VISIBLE_GROUP + " DESC, " 523f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa + "(CASE WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_CURRENT 52446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 0 " 525f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa + " WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_RECENT 52646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 1 " 52746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " ELSE 2 END), " 52846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.TIMES_USED + " DESC, " 52946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Contacts.DISPLAY_NAME + ", " 53046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Data.CONTACT_ID + ", " 531c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_SUPER_PRIMARY + " DESC, " 532c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_PRIMARY + " DESC"; 53346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 53446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** Currently same as {@link #EMAIL_FILTER_SORT_ORDER} */ 53546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final String PHONE_FILTER_SORT_ORDER = EMAIL_FILTER_SORT_ORDER; 536c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 537916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 538916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 539916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 540916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 54192ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov NameLookupType.NICKNAME; 542916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 543f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov /** 544f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * If any of these columns are used in a Data projection, there is no point in 545f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * using the DISTINCT keyword, which can negatively affect performance. 546f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov */ 547f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov private static final String[] DISTINCT_DATA_PROHIBITING_COLUMNS = { 548f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data._ID, 549f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.RAW_CONTACT_ID, 550f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.NAME_RAW_CONTACT_ID, 551f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 552f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 55343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.DATA_SET, 55443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 555f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.DIRTY, 556f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.NAME_VERIFIED, 557f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SOURCE_ID, 558f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.VERSION, 559f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov }; 560916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 561f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsColumns = ProjectionMap.builder() 562f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CUSTOM_RINGTONE) 563f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME) 564f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_ALTERNATIVE) 565f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_SOURCE) 566f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.IN_VISIBLE_GROUP) 567f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LAST_TIME_CONTACTED) 568f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LOOKUP_KEY) 569f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME) 570f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME_STYLE) 571f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHOTO_ID) 572f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .add(Contacts.PHOTO_FILE_ID) 5733d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_URI) 5743d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_THUMBNAIL_URI) 575f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SEND_TO_VOICEMAIL) 576f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_ALTERNATIVE) 577f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_PRIMARY) 578f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.STARRED) 579f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.TIMES_CONTACTED) 580cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 581f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 582f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 583f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsPresenceColumns = ProjectionMap.builder() 584f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 585f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE) 586f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 587f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 588f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 589f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 590f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 591f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 592f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 593f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 594f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 595f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 596f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 597f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 598f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 599f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 600f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSnippetColumns = ProjectionMap.builder() 60103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov .add(SearchSnippetColumns.SNIPPET) 602f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 603f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 604f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactColumns = ProjectionMap.builder() 605f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_NAME) 606f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_TYPE) 60743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(RawContacts.DATA_SET) 60843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(RawContacts.ACCOUNT_TYPE_AND_DATA_SET) 609f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DIRTY) 610f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.NAME_VERIFIED) 611f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SOURCE_ID) 612f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.VERSION) 613f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 614f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 615f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactSyncColumns = ProjectionMap.builder() 616f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC1) 617f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC2) 618f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC3) 619f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC4) 620f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 621f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 622f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataColumns = ProjectionMap.builder() 623f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA1) 624f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA2) 625f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA3) 626f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA4) 627f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA5) 628f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA6) 629f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA7) 630f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA8) 631f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA9) 632f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA10) 633f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA11) 634f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA12) 635f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA13) 636f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA14) 637f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA15) 638f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA_VERSION) 639f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_PRIMARY) 640f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_SUPER_PRIMARY) 641f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.MIMETYPE) 642f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RES_PACKAGE) 643f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC1) 644f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC2) 645f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC3) 646f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC4) 647f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(GroupMembership.GROUP_SOURCE_ID) 648f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 649f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 650f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactPresenceColumns = ProjectionMap.builder() 651f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 652f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.PRESENCE) 653f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 654f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.CHAT_CAPABILITY) 655f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 656f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 657f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 658f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 659f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 660f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 661f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 662f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 663f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 664f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 665f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 666f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 667f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataPresenceColumns = ProjectionMap.builder() 668f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.PRESENCE, Tables.PRESENCE + "." + StatusUpdates.PRESENCE) 669f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CHAT_CAPABILITY, Tables.PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 670f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS, StatusUpdatesColumns.CONCRETE_STATUS) 671f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_TIMESTAMP, StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 672f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_RES_PACKAGE, StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 673f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_LABEL, StatusUpdatesColumns.CONCRETE_STATUS_LABEL) 674f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_ICON, StatusUpdatesColumns.CONCRETE_STATUS_ICON) 675f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 676f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 677038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 678f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sCountProjectionMap = ProjectionMap.builder() 679f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(BaseColumns._COUNT, "COUNT(*)") 680f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 681f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 682e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 683f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionMap = ProjectionMap.builder() 684f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts._ID) 685f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 686f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.NAME_RAW_CONTACT_ID) 68724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 688f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 689f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsPresenceColumns) 690f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 691f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 692916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 693f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionWithSnippetMap = ProjectionMap.builder() 694f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 695f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sSnippetColumns) 696f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 697916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6985e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 699f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentStarredProjectionMap = ProjectionMap.builder() 700f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 7012f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 702f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 703f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 704f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder() 705f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 7062f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, "SUM(" + DataUsageStatColumns.CONCRETE_TIMES_USED + ")") 707f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 708f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7094928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa /** 7104928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Used for Strequent Uri with {@link ContactsContract#STREQUENT_PHONE_ONLY}, which allows 7114928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * users to obtain part of Data columns. Right now Starred part just returns NULL for 7124928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * those data columns (frequent part should return real ones in data table). 7134928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa **/ 7144928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa private static final ProjectionMap sStrequentPhoneOnlyStarredProjectionMap 7154928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa = ProjectionMap.builder() 7164928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .addAll(sContactsProjectionMap) 7174928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 7184928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.NUMBER, "NULL") 7194928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.TYPE, "NULL") 7204928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.LABEL, "NULL") 7214928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .build(); 7224928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 7234928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa /** 7244928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Used for Strequent Uri with {@link ContactsContract#STREQUENT_PHONE_ONLY}, which allows 7254928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * users to obtain part of Data columns. We hard-code {@link Contacts#IS_USER_PROFILE} to NULL, 7264928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * because sContactsProjectionMap specifies a field that doesn't exist in the view behind the 7274928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * query that uses this projection map. 7284928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa **/ 7294928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa private static final ProjectionMap sStrequentPhoneOnlyFrequentProjectionMap 7304928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa = ProjectionMap.builder() 7314928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .addAll(sContactsProjectionMap) 7324928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, DataUsageStatColumns.CONCRETE_TIMES_USED) 7334928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.NUMBER) 7344928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.TYPE) 7354928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.LABEL) 7364928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Contacts.IS_USER_PROFILE, "NULL") 7374928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .build(); 7384928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 739f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 740f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsVCardProjectionMap = ProjectionMap.builder() 741fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen .add(Contacts._ID) 742f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME + " || '.vcf'") 743f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.SIZE, "NULL") 744f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 745f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 746ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 747f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactsProjectionMap = ProjectionMap.builder() 748f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 749f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 750f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 751f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_PRIMARY) 752f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_ALTERNATIVE) 753f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_SOURCE) 754f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME) 755f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME_STYLE) 756f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_PRIMARY) 757f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_ALTERNATIVE) 758f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.TIMES_CONTACTED) 759f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.LAST_TIME_CONTACTED) 760f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CUSTOM_RINGTONE) 761f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SEND_TO_VOICEMAIL) 762f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 763f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.AGGREGATION_MODE) 76424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 765f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 766f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 767f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 768f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 769a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the raw entity view*/ 770f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawEntityProjectionMap = ProjectionMap.builder() 771f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 772f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 773f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.Entity.DATA_ID) 774f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 775f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 77624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 777f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 778f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 779f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 780f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 781f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 782a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the contact entity view*/ 783f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sEntityProjectionMap = ProjectionMap.builder() 784f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity._ID) 785f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.CONTACT_ID) 786f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.RAW_CONTACT_ID) 787f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DATA_ID) 788f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.NAME_RAW_CONTACT_ID) 789f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DELETED) 79024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 791f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 792f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 793f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 794f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 795f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 796f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 797f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 798f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 79958795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda /** Contains columns in PhoneLookup which are not contained in the data view. */ 80058795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda private static final ProjectionMap sSipLookupColumns = ProjectionMap.builder() 80158795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .add(PhoneLookup.NUMBER, SipAddress.SIP_ADDRESS) 80258795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .add(PhoneLookup.TYPE, "0") 80358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .add(PhoneLookup.LABEL, "NULL") 80458795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .add(PhoneLookup.NORMALIZED_NUMBER, "NULL") 80558795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .build(); 80658795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda 8074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 808f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataProjectionMap = ProjectionMap.builder() 809f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID) 810f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RAW_CONTACT_ID) 811f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CONTACT_ID) 812f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.NAME_RAW_CONTACT_ID) 81324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 814f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 815f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 816f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 817f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 818f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 819f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 820f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 82158795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda /** Contains columns from the data view used for SIP address lookup. */ 82258795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda private static final ProjectionMap sDataSipLookupProjectionMap = ProjectionMap.builder() 82358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .addAll(sDataProjectionMap) 82458795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .addAll(sSipLookupColumns) 82558795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .build(); 82658795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda 8275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 828f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDistinctDataProjectionMap = ProjectionMap.builder() 829f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID, "MIN(" + Data._ID + ")") 830f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 83124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 832f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 833f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 834f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 835f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 836f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 837f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 83858795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda /** Contains columns from the data view used for SIP address lookup. */ 83958795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda private static final ProjectionMap sDistinctDataSipLookupProjectionMap = ProjectionMap.builder() 84058795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .addAll(sDistinctDataProjectionMap) 84158795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .addAll(sSipLookupColumns) 84258795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda .build(); 84358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda 8449261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 845f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sPhoneLookupProjectionMap = ProjectionMap.builder() 846f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup._ID, "contacts_view." + Contacts._ID) 847f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LOOKUP_KEY, "contacts_view." + Contacts.LOOKUP_KEY) 848f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.DISPLAY_NAME, "contacts_view." + Contacts.DISPLAY_NAME) 849f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LAST_TIME_CONTACTED, "contacts_view." + Contacts.LAST_TIME_CONTACTED) 850f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TIMES_CONTACTED, "contacts_view." + Contacts.TIMES_CONTACTED) 851f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.STARRED, "contacts_view." + Contacts.STARRED) 852f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.IN_VISIBLE_GROUP, "contacts_view." + Contacts.IN_VISIBLE_GROUP) 853f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.PHOTO_ID, "contacts_view." + Contacts.PHOTO_ID) 8543d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_URI, "contacts_view." + Contacts.PHOTO_URI) 8553d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_THUMBNAIL_URI, "contacts_view." + Contacts.PHOTO_THUMBNAIL_URI) 856f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.CUSTOM_RINGTONE, "contacts_view." + Contacts.CUSTOM_RINGTONE) 857f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.HAS_PHONE_NUMBER, "contacts_view." + Contacts.HAS_PHONE_NUMBER) 858f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.SEND_TO_VOICEMAIL, "contacts_view." + Contacts.SEND_TO_VOICEMAIL) 859f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.NUMBER, Phone.NUMBER) 860f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TYPE, Phone.TYPE) 861f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LABEL, Phone.LABEL) 8622530512f639c4979fd7371c7dd25dd67e8118124Bai Tao .add(PhoneLookup.NORMALIZED_NUMBER, Phone.NORMALIZED_NUMBER) 863f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 864f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 865ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 866f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsProjectionMap = ProjectionMap.builder() 867f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups._ID) 868f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_NAME) 869f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_TYPE) 87043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(Groups.DATA_SET) 87143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(Groups.ACCOUNT_TYPE_AND_DATA_SET) 872f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SOURCE_ID) 873f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DIRTY) 874f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.VERSION) 875f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.RES_PACKAGE) 876f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE) 877f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE_RES) 878f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.GROUP_VISIBLE) 879f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYSTEM_ID) 880f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DELETED) 881f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.NOTES) 882f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SHOULD_SYNC) 883f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.FAVORITES) 884f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.AUTO_ADD) 885c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov .add(Groups.GROUP_IS_READ_ONLY) 886f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC1) 887f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC2) 888f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC3) 889f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC4) 890f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 891f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 89223ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki /** 89323ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki * Contains {@link Groups} columns along with summary details. 89423ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki * 89523ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki * Note {@link Groups#SUMMARY_COUNT} doesn't exist in groups/view_groups. 89623ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki * When we detect this column being requested, we join {@link Joins#GROUP_MEMBER_COUNT} to 89723ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki * generate it. 89823ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki */ 899f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsSummaryProjectionMap = ProjectionMap.builder() 900f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sGroupsProjectionMap) 90123ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki .add(Groups.SUMMARY_COUNT, "ifnull(group_member_count, 0)") 902f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_WITH_PHONES, 903f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(" + ContactsColumns.CONCRETE_ID + ") FROM " 904f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Tables.CONTACTS_JOIN_RAW_CONTACTS_DATA_FILTERED_BY_GROUPMEMBERSHIP 905f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " WHERE " + Contacts.HAS_PHONE_NUMBER + ")") 906f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .build(); 907f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa 908f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa // This is only exposed as hidden API for the contacts app, so we can be very specific in 909f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa // the filtering 910f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa private static final ProjectionMap sGroupsSummaryProjectionMapWithGroupCountPerAccount = 911f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa ProjectionMap.builder() 912f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .addAll(sGroupsSummaryProjectionMap) 913f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .add(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT, 914f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(*) FROM " + Views.GROUPS + " WHERE " 915f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + "(" + Groups.ACCOUNT_NAME + "=" 916f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + GroupsColumns.CONCRETE_ACCOUNT_NAME 917f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " AND " 918f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.ACCOUNT_TYPE + "=" + GroupsColumns.CONCRETE_ACCOUNT_TYPE 919f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " AND " 920f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.DELETED + "=0 AND " 921f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.FAVORITES + "=0 AND " 922f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.AUTO_ADD + "=0" 923f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")" 924f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " GROUP BY " 925f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.ACCOUNT_NAME + ", " + Groups.ACCOUNT_TYPE 926f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")") 927f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 928f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 929373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 930f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sAggregationExceptionsProjectionMap = ProjectionMap.builder() 931f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id") 932f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.TYPE) 933f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID1) 934f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID2) 935f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 936f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 937eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 938f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSettingsProjectionMap = ProjectionMap.builder() 939f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_NAME) 940f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_TYPE) 941f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro .add(Settings.DATA_SET) 942f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_VISIBLE) 943f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.SHOULD_SYNC) 944f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ANY_UNSYNCED, 945f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 946f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ",(SELECT " 947f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "(CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL" 948f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 949f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE MIN(" + Groups.SHOULD_SYNC + ")" 950f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)" 951f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.GROUPS 952f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 953f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_NAME 954f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 955f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_ACCOUNT_TYPE 956f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + " AND ((" + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 957f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_DATA_SET + " IS NULL) OR (" 958f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + GroupsColumns.CONCRETE_DATA_SET + "=" 959f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_DATA_SET + "))))=0" 960f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 961f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE 0" 962f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)") 963f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_COUNT, 964f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 965f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 966f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 967f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 968f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 969f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 970f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_WITH_PHONES, 971f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 972f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 973f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 974f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Contacts.HAS_PHONE_NUMBER 975f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 976f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 977f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 978f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 979f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 98082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 981f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStatusUpdatesProjectionMap = ProjectionMap.builder() 982f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PresenceColumns.RAW_CONTACT_ID) 983f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.DATA_ID, DataColumns.CONCRETE_ID) 984f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_ACCOUNT) 985f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_HANDLE) 986f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PROTOCOL) 987f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 988f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // properly enforce uniqueness of null values 989f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CUSTOM_PROTOCOL, 990f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL + "=''" 991f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN NULL" 992f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END)") 993f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PRESENCE) 994f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CHAT_CAPABILITY) 995f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS) 996f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_TIMESTAMP) 997f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_RES_PACKAGE) 998f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_ICON) 999f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_LABEL) 1000f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 1001f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 10023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Contains StreamItems columns */ 10033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemsProjectionMap = ProjectionMap.builder() 10049b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems._ID) 10059b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.CONTACT_ID) 1006af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann .add(StreamItems.CONTACT_LOOKUP_KEY) 10079b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.ACCOUNT_NAME) 10089b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.ACCOUNT_TYPE) 10099b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.DATA_SET) 10103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 10119b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.RAW_CONTACT_SOURCE_ID) 10123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_PACKAGE) 10133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_ICON) 10143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_LABEL) 10153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TEXT) 10163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TIMESTAMP) 10173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.COMMENTS) 10180bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC1) 10190bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC2) 10200bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC3) 10210bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC4) 10223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 10233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 10243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemPhotosProjectionMap = ProjectionMap.builder() 10253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos._ID, StreamItemPhotosColumns.CONCRETE_ID) 10263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 10270bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.RAW_CONTACT_SOURCE_ID, RawContactsColumns.CONCRETE_SOURCE_ID) 10283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.STREAM_ITEM_ID) 10293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.SORT_INDEX) 10306802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .add(StreamItemPhotos.PHOTO_FILE_ID) 10316802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .add(StreamItemPhotos.PHOTO_URI, 10326802030a777c0c3ba1dc029c534cca4784260632Dave Santoro "'" + DisplayPhoto.CONTENT_URI + "'||'/'||" + StreamItemPhotos.PHOTO_FILE_ID) 10331dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.HEIGHT) 10341dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.WIDTH) 10351dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.FILESIZE) 10360bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC1) 10370bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC2) 10380bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC3) 10390bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC4) 10403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 10413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 1042d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** Contains {@link Directory} columns */ 1043f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDirectoryProjectionMap = ProjectionMap.builder() 1044f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory._ID) 1045f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.PACKAGE_NAME) 1046f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.TYPE_RESOURCE_ID) 1047f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DISPLAY_NAME) 1048f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DIRECTORY_AUTHORITY) 1049f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_TYPE) 1050f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_NAME) 1051f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.EXPORT_SUPPORT) 1052778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.SHORTCUT_SUPPORT) 1053778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.PHOTO_SUPPORT) 1054f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 10557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 10569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 10579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 10589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 10599705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 10609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 10619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 10622526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 10632526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 1064bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1065bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 1066bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1067bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 106851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 106903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_START_MATCH = "["; 107003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_END_MATCH = "]"; 107103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_ELLIPSIS = "..."; 107203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final int DEFAULT_SNIPPET_ARG_MAX_TOKENS = -10; 107303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 10749a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhoneInitialized; 10759a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhone; 10769a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 1077f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 10781129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 10791129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 10802526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 10812526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 1082f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 1083f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 108446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 108546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Stores mapping from type Strings exposed via {@link DataUsageFeedback} to 108646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type integers in {@link DataUsageStatColumns}. 108746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 108846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final Map<String, Integer> sDataUsageTypeMap; 108946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 10904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 10914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 1092a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 1093d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 1094d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 1095a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA); 1096a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES); 10973653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 10983653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 10992d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 11002d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 1101a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO); 1102f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/display_photo", 1103f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_ID_DISPLAY_PHOTO); 11043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/stream_items", 11053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_ID_STREAM_ITEMS); 1106c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); 11075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 11085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 11092149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA); 1110bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/photo", 1111bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro CONTACTS_LOOKUP_PHOTO); 11125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 11132149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", 11142149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov CONTACTS_LOOKUP_ID_DATA); 1115bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/photo", 1116bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro CONTACTS_LOOKUP_ID_PHOTO); 1117f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/display_photo", 1118f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_LOOKUP_DISPLAY_PHOTO); 1119f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/display_photo", 1120f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_LOOKUP_ID_DISPLAY_PHOTO); 1121a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", 1122a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ENTITIES); 1123a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", 1124a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ID_ENTITIES); 11253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/stream_items", 11263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_STREAM_ITEMS); 11273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/stream_items", 11283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_ID_STREAM_ITEMS); 1129f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 113042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 113142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 11325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 1133ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 1134ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 11355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 113645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "contacts/frequent", CONTACTS_FREQUENT); 11373653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 11385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 11395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 11405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 1141f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/display_photo", 1142f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro RAW_CONTACTS_ID_DISPLAY_PHOTO); 114346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 11443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items", 11453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann RAW_CONTACTS_ID_STREAM_ITEMS); 114682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items/#", 114782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro RAW_CONTACTS_ID_STREAM_ITEMS_ID); 114846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 114946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 1150b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 11514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 11524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 1153ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 115448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 11555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 1156ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 11574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 115848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 11591dac83b8fa58944acfd00f44e717a7dddc659d2dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup", EMAILS_LOOKUP); 11605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 11615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 11624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 1163ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 116448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 116546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** "*" is in CSV form with data ids ("123,456,789") */ 116646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "data/usagefeedback/*", DATA_USAGE_FEEDBACK_ID); 11671f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1168ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 1169ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 1170ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 1171ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 117235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 1173b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 1174b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 11755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/" + SyncStateContentProviderHelper.PATH, 11765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_SYNCSTATE); 11775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, 11785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "profile/" + SyncStateContentProviderHelper.PATH + "/#", 11795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_SYNCSTATE_ID); 118035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1181a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 1182b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 1183b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 1184b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 1185b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 11864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1187eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 1188eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 118982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 119082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 11911f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1192c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 1193c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 1194c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 1195c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 11962d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 1197c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 1198c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 119909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 1200d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1201d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories", DIRECTORIES); 1202d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories/#", DIRECTORIES_ID); 12037a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 12047a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "complete_name", COMPLETE_NAME); 120524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 120624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile", PROFILE); 120724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/entities", PROFILE_ENTITIES); 120824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data", PROFILE_DATA); 120924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data/#", PROFILE_DATA_ID); 121085077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/photo", PROFILE_PHOTO); 121185077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/display_photo", PROFILE_DISPLAY_PHOTO); 121224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/as_vcard", PROFILE_AS_VCARD); 121324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts", PROFILE_RAW_CONTACTS); 121424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#", 121524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID); 121624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/data", 121724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_DATA); 121824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/entity", 121924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_ENTITIES); 12205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/status_updates", 12215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_STATUS_UPDATES); 12223202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contact_entities", 12233202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro PROFILE_RAW_CONTACT_ENTITIES); 122446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 12253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items", STREAM_ITEMS); 12263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/photo", STREAM_ITEMS_PHOTOS); 12273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#", STREAM_ITEMS_ID); 12283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo", STREAM_ITEMS_ID_PHOTOS); 12293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo/#", 12303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann STREAM_ITEMS_ID_PHOTOS_ID); 12313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items_limit", STREAM_ITEMS_LIMIT); 12323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 12335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "display_photo/#", DISPLAY_PHOTO); 1234f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "photo_dimensions", PHOTO_DIMENSIONS); 1235f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 123646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa HashMap<String, Integer> tmpTypeMap = new HashMap<String, Integer>(); 123746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_CALL, DataUsageStatColumns.USAGE_TYPE_INT_CALL); 123846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_LONG_TEXT, 123946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT); 124046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_SHORT_TEXT, 124146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_SHORT_TEXT); 124246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sDataUsageTypeMap = Collections.unmodifiableMap(tmpTypeMap); 124319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 124419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 1245d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static class DirectoryInfo { 1246d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String authority; 1247d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountName; 1248d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountType; 1249d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 1250d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1251d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 1252d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Cached information about contact directories. 1253d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 12544458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private HashMap<String, DirectoryInfo> mDirectoryCache = new HashMap<String, DirectoryInfo>(); 12554458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private boolean mDirectoryCacheValid = false; 1256d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 12573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 125843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * An entry in group id cache. It maps the combination of (account type, account name, data set, 1259ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1260ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1261e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov public static class GroupIdCacheEntry { 1262ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1263ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 126443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet; 1265ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1266ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1267ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1268a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1269e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1270e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1271e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // is a list of groups with this group id. 1272e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1273e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov 127424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 1275f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Maximum dimension (height or width) of display photos. Larger images will be scaled 1276f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * to fit. 1277f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 1278f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private int mMaxDisplayPhotoDim; 1279f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1280f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 1281f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Maximum dimension (height or width) of photo thumbnails. 1282f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 1283f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private int mMaxThumbnailPhotoDim; 1284f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 12855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 12865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Sub-provider for handling profile requests against the profile database. 12875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 12885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ProfileProvider mProfileProvider; 1289f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 12904097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1291f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1292315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1293622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1294622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 129572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private ContactDirectoryManager mContactDirectoryManager; 12965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1297078f588cef389358adabc579de00747878f3c108Dave Santoro // The database tag to use for representing the contacts DB in contacts transactions. 1298078f588cef389358adabc579de00747878f3c108Dave Santoro /* package */ static final String CONTACTS_DB_TAG = "contacts"; 1299078f588cef389358adabc579de00747878f3c108Dave Santoro 1300078f588cef389358adabc579de00747878f3c108Dave Santoro // The database tag to use for representing the profile DB in contacts transactions. 1301078f588cef389358adabc579de00747878f3c108Dave Santoro /* package */ static final String PROFILE_DB_TAG = "profile"; 1302078f588cef389358adabc579de00747878f3c108Dave Santoro 13035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 13045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * The active (thread-local) database. This will be switched between a contacts-specific 13055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database and a profile-specific database, depending on what the current operation is 13065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * targeted to. 13075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 13085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<SQLiteDatabase> mActiveDb = new ThreadLocal<SQLiteDatabase>(); 13095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13106efb7db26598b105342d02207e0ca1c8725c10daDave Santoro /** 13116efb7db26598b105342d02207e0ca1c8725c10daDave Santoro * The thread-local holder of the active transaction. Shared between this and the profile 13126efb7db26598b105342d02207e0ca1c8725c10daDave Santoro * provider, to keep transactions on both databases synchronized. 13136efb7db26598b105342d02207e0ca1c8725c10daDave Santoro */ 13146efb7db26598b105342d02207e0ca1c8725c10daDave Santoro private final ThreadLocal<ContactsTransaction> mTransactionHolder = 13156efb7db26598b105342d02207e0ca1c8725c10daDave Santoro new ThreadLocal<ContactsTransaction>(); 13166efb7db26598b105342d02207e0ca1c8725c10daDave Santoro 13175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This variable keeps track of whether the current operation is intended for the profile DB. 13185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mInProfileMode = new ThreadLocal<Boolean>(); 13195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Separate data row handler instances for contact data and profile data. 13215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private HashMap<String, DataRowHandler> mDataRowHandlers; 13225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private HashMap<String, DataRowHandler> mProfileDataRowHandlers; 13235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile, we will use one of two 13255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // database helper instances. 13265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<ContactsDatabaseHelper> mDbHelper = 13275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<ContactsDatabaseHelper>(); 13285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ContactsDatabaseHelper mContactsHelper; 13295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ProfileDatabaseHelper mProfileHelper; 13305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile or not, we will use one of 13325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // two aggregator instances. 13335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<ContactAggregator> mAggregator = new ThreadLocal<ContactAggregator>(); 1334622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 13355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ContactAggregator mProfileAggregator; 13365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile or not, we will use one of 13385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // two photo store instances (with their files stored in separate subdirectories). 13395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<PhotoStore> mPhotoStore = new ThreadLocal<PhotoStore>(); 13405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private PhotoStore mContactsPhotoStore; 13415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private PhotoStore mProfilePhotoStore; 13425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // The active transaction context will switch depending on the operation being performed. 13445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Both transaction contexts will be cleared out when a batch transaction is started, and 13455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // each will be processed separately when a batch transaction completes. 13465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private TransactionContext mContactTransactionContext = new TransactionContext(false); 13475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private TransactionContext mProfileTransactionContext = new TransactionContext(true); 13485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<TransactionContext> mTransactionContext = 13495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<TransactionContext>(); 13505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 135182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // Duration in milliseconds that pre-authorized URIs will remain valid. 135282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro private long mPreAuthorizedUriDuration; 135382792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 135482792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // Map of single-use pre-authorized URIs to expiration times. 135582792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro private Map<Uri, Long> mPreAuthorizedUris = Maps.newHashMap(); 135682792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 1357d0eb93009559d095de0448907527aeb059801dc4Dave Santoro // Random number generator. 1358d0eb93009559d095de0448907527aeb059801dc4Dave Santoro private SecureRandom mRandom = new SecureRandom(); 135982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 1360f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1361a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1362d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1363f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private SearchIndexManager mSearchIndexManager; 1364a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 136520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 136673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 136720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 136809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 13693826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private boolean mProviderStatusUpdateNeeded; 137009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 137115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mReadAccessLatch; 137215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mWriteAccessLatch; 137315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private boolean mAccountUpdateListenerRegistered; 1374bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private boolean mOkToOpenAccess = true; 137573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 13761a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 13771a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 137881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 137981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 13804cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 13813826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private int mContactsAccountCount; 1382d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1383bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private HandlerThread mBackgroundThread; 1384bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private Handler mBackgroundHandler; 1385bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1386f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private long mLastPhotoCleanup = 0; 1387f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 13884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 13894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1390663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 1391663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "ContactsProvider2.onCreate start"); 1392663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 1393de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1394ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1395ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1396ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1397ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1398ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1399663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } finally { 1400663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 1401663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "ContactsProvider2.onCreate finish"); 1402663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 1403ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1404ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 140535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1406ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 140715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov StrictMode.setThreadPolicy( 140815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); 140915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 14103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Resources resources = getContext().getResources(); 1411f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxDisplayPhotoDim = resources.getInteger( 1412f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro R.integer.config_max_display_photo_dim); 1413f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxThumbnailPhotoDim = resources.getInteger( 1414f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro R.integer.config_max_thumbnail_photo_dim); 14153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 1416078f588cef389358adabc579de00747878f3c108Dave Santoro mContactsHelper = getDatabaseHelper(getContext()); 14175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mContactsHelper); 1418078f588cef389358adabc579de00747878f3c108Dave Santoro 1419078f588cef389358adabc579de00747878f3c108Dave Santoro // Set up the DB helper for keeping transactions serialized. 1420078f588cef389358adabc579de00747878f3c108Dave Santoro setDbHelperToSerializeOn(mContactsHelper, CONTACTS_DB_TAG); 1421078f588cef389358adabc579de00747878f3c108Dave Santoro 142272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager = new ContactDirectoryManager(this); 1423a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 142465ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 1425bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // The provider is closed for business until fully initialized 142615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = new CountDownLatch(1); 142715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = new CountDownLatch(1); 142872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1429bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread = new HandlerThread("ContactsProviderWorker", 1430bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Process.THREAD_PRIORITY_BACKGROUND); 1431bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread.start(); 1432bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { 1433bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 1434bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void handleMessage(Message msg) { 1435bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov performBackgroundTask(msg.what, msg.obj); 1436bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1437bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov }; 14382a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 14395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Set up the sub-provider for handling profiles. 14405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileProvider = getProfileProvider(); 1441c990980ab4beb7b81c3337526f1bdcd5d1a14730Dave Santoro mProfileProvider.setDbHelperToSerializeOn(mContactsHelper, CONTACTS_DB_TAG); 14425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ProviderInfo profileInfo = new ProviderInfo(); 14435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileInfo.readPermission = "android.permission.READ_PROFILE"; 14445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileInfo.writePermission = "android.permission.WRITE_PROFILE"; 14455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileProvider.attachInfo(getContext(), profileInfo); 1446078f588cef389358adabc579de00747878f3c108Dave Santoro mProfileHelper = mProfileProvider.getDatabaseHelper(getContext()); 14475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 144882792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // Initialize the pre-authorized URI duration. 144982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro mPreAuthorizedUriDuration = android.provider.Settings.Secure.getLong( 145082792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro getContext().getContentResolver(), 145182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro android.provider.Settings.Secure.CONTACTS_PREAUTH_URI_EXPIRATION, 145282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro DEFAULT_PREAUTHORIZED_URI_EXPIRATION); 145382792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 145415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_INITIALIZE); 1455bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1456bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 1457bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_LOCALE); 1458bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM); 145905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_SEARCH_INDEX); 1460bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_PROVIDER_STATUS); 146115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_OPEN_WRITE_ACCESS); 1462f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 14633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 146449d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov return true; 14654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 14664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1467767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 146851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 146951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 147004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 147115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 14725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mLegacyApiSupport = new LegacyApiSupport(context, mContactsHelper, this, 14735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mGlobalSearchSupport); 14744cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 14755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mNameSplitter = mContactsHelper.createNameSplitter(); 14764cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 14774cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 14785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mCommonNicknameCache = new CommonNicknameCache(mContactsHelper.getReadableDatabase()); 1479cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 14805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator = new ContactAggregator(this, mContactsHelper, 148115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 14825b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 14835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator = new ProfileAggregator(this, mProfileHelper, 14845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 14855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1486f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSearchIndexManager = new SearchIndexManager(this); 14875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 14885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore = new PhotoStore(getContext().getFilesDir(), mContactsHelper); 14895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore = new PhotoStore(new File(getContext().getFilesDir(), "profile"), 14905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper); 14915b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 1492bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 14935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro initDataRowHandlers(mDataRowHandlers, mContactsHelper, mContactAggregator, 14945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore); 14955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDataRowHandlers = new HashMap<String, DataRowHandler>(); 14965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro initDataRowHandlers(mProfileDataRowHandlers, mProfileHelper, mProfileAggregator, 14975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore); 14985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 14995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Set initial thread-local state variables for the Contacts DB. 15005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 15015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 1502bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 15035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void initDataRowHandlers(Map<String, DataRowHandler> handlerMap, 15045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ContactsDatabaseHelper dbHelper, ContactAggregator contactAggregator, 15055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore photoStore) { 15065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Context context = getContext(); 15075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Email.CONTENT_ITEM_TYPE, 15085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForEmail(context, dbHelper, contactAggregator)); 15095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Im.CONTENT_ITEM_TYPE, 15105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForIm(context, dbHelper, contactAggregator)); 15115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Organization.CONTENT_ITEM_TYPE, 15125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForOrganization(context, dbHelper, contactAggregator)); 15135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Phone.CONTENT_ITEM_TYPE, 15145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForPhoneNumber(context, dbHelper, contactAggregator)); 15155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Nickname.CONTENT_ITEM_TYPE, 15165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForNickname(context, dbHelper, contactAggregator)); 15175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(StructuredName.CONTENT_ITEM_TYPE, 15185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForStructuredName(context, dbHelper, contactAggregator, 1519bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mNameSplitter, mNameLookupBuilder)); 15205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(StructuredPostal.CONTENT_ITEM_TYPE, 15215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForStructuredPostal(context, dbHelper, contactAggregator, 1522bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mPostalSplitter)); 15235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(GroupMembership.CONTENT_ITEM_TYPE, 15245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForGroupMembership(context, dbHelper, contactAggregator, 1525bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mGroupIdCache)); 15265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Photo.CONTENT_ITEM_TYPE, 15275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForPhoto(context, dbHelper, contactAggregator, photoStore)); 15285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Note.CONTENT_ITEM_TYPE, 15295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForNote(context, dbHelper, contactAggregator)); 1530bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1531bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1532bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /** 1533bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Visible for testing. 1534bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov */ 1535bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 1536bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return new PhotoPriorityResolver(context); 1537bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1538bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1539bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task) { 1540bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendEmptyMessage(task); 1541bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1542bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1543bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task, Object arg) { 1544bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(task, arg)); 1545bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1546bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1547bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void performBackgroundTask(int task, Object arg) { 1548bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov switch (task) { 154915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_INITIALIZE: { 155015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov initForDefaultLocale(); 155115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch.countDown(); 155215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = null; 155315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov break; 155415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 155515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 155615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_OPEN_WRITE_ACCESS: { 1557bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (mOkToOpenAccess) { 155815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch.countDown(); 155915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = null; 1560bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1561bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1562bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1563bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1564bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS: { 1565bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1566bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov importLegacyContactsInBackground(); 1567bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1568bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1569bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1570bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1571bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_ACCOUNTS: { 157215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 157315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (!mAccountUpdateListenerRegistered) { 157415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov AccountManager.get(context).addOnAccountsUpdatedListener(this, null, false); 157515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mAccountUpdateListenerRegistered = true; 157615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 157715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 15785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Update the accounts for both the contacts and profile DBs. 157915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Account[] accounts = AccountManager.get(context).getAccounts(); 15805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 1581bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean accountsChanged = updateAccountsInBackground(accounts); 15825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 15835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro accountsChanged |= updateAccountsInBackground(accounts); 15845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1585bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateContactsAccountCount(accounts); 1586bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateDirectoriesInBackground(accountsChanged); 1587bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1588bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1589bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1590bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_LOCALE: { 1591bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateLocaleInBackground(); 1592bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1593bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1594bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1595fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov case BACKGROUND_TASK_CHANGE_LOCALE: { 1596fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov changeLocaleInBackground(); 1597fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov break; 1598fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1599fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1600bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM: { 1601bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isAggregationUpgradeNeeded()) { 1602bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov upgradeAggregationAlgorithmInBackground(); 1603bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1604bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1605bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1606bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 160705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_SEARCH_INDEX: { 160805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov updateSearchIndexInBackground(); 160905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov break; 161005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 161105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1612bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_PROVIDER_STATUS: { 1613bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateProviderStatus(); 1614bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1615bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1616bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1617bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_DIRECTORIES: { 1618bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (arg != null) { 1619bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.onPackageChanged((String) arg); 1620bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1621bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1622bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1623f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1624f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case BACKGROUND_TASK_CLEANUP_PHOTOS: { 1625f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Check rate limit. 1626f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long now = System.currentTimeMillis(); 1627f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (now - mLastPhotoCleanup > PHOTO_CLEANUP_RATE_LIMIT) { 1628f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mLastPhotoCleanup = now; 16295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 16305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Clean up photo stores for both contacts and profiles. 16315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 16325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cleanupPhotoStore(); 16335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 1634f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro cleanupPhotoStore(); 1635f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro break; 1636f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1637f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1638bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 16394cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 16404cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 164153fac8f99f3884c372c907a76766d27fa9e1d95fDmitri Plotnikov public void onLocaleChanged() { 16423826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 16433826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 16444f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov return; 16454f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov } 16464f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 1647fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_CHANGE_LOCALE); 16484cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 164951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 165051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 165151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 165251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 165351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 165451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 165551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 165651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 1657bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateLocaleInBackground() { 1658f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 1659f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 1660f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 1661f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 1662f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 1663f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 166451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 166551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 166651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 166751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 166851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 166951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 167051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 167151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 167251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 16735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setLocale(this, currentLocale); 16745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper.setLocale(this, currentLocale); 1675bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).apply(); 1676bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov setProviderStatus(providerStatus); 1677bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 167851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1679fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov /** 1680fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov * Reinitializes the provider for a new locale. 1681fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov */ 1682fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private void changeLocaleInBackground() { 1683fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Re-initializing the provider without stopping it. 1684fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Locking the database will prevent inserts/updates/deletes from 1685fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // running at the same time, but queries may still be running 1686fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // on other threads. Those queries may return inconsistent results. 16875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mContactsHelper.getWritableDatabase(); 16885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase profileDb = mProfileHelper.getWritableDatabase(); 1689fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.beginTransaction(); 16905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.beginTransaction(); 1691fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov try { 1692fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov initForDefaultLocale(); 1693fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.setTransactionSuccessful(); 16945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.setTransactionSuccessful(); 1695fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } finally { 1696fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.endTransaction(); 16975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.endTransaction(); 1698fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1699fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1700fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov updateLocaleInBackground(); 1701fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1702fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 170305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov protected void updateSearchIndexInBackground() { 170405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mSearchIndexManager.updateIndex(); 170505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 170605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1707bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateDirectoriesInBackground(boolean rescan) { 1708bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanAllPackages(rescan); 170951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 171051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 17113826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateProviderStatus() { 17123826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 17133826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 17143826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return; 17153826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 17163826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 17173e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson // No accounts/no contacts status is true if there are no account and 17185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // there are no contacts or one profile contact 17193e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson if (mContactsAccountCount == 0) { 17205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactsNum = DatabaseUtils.queryNumEntries(mContactsHelper.getReadableDatabase(), 17213e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson Tables.CONTACTS, null); 17225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long profileNum = DatabaseUtils.queryNumEntries(mProfileHelper.getReadableDatabase(), 17235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Tables.CONTACTS, null); 17245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 17255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // TODO: Different status if there is a profile but no contacts? 17265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (contactsNum == 0 && profileNum <= 1) { 17273e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson setProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 17283e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson } else { 17293e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson setProviderStatus(ProviderStatus.STATUS_NORMAL); 17303e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson } 17313826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } else { 17323826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 17333826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 17343826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 17353826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 173631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1737f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro protected void cleanupPhotoStore() { 17385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); 1739d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro mActiveDb.set(db); 17406802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 17416802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Assemble the set of photo store file IDs that are in use, and send those to the photo 1742f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // store. Any photos that aren't in that set will be deleted, and any photos that no 1743f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // longer exist in the photo store will be returned for us to clear out in the DB. 17447cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimeTypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 17456802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Cursor c = db.query(Views.DATA, new String[]{Data._ID, Photo.PHOTO_FILE_ID}, 17467cf50494501938f175d288077145acf49da8f171Daniel Lehmann DataColumns.MIMETYPE_ID + "=" + photoMimeTypeId + " AND " 1747f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro + Photo.PHOTO_FILE_ID + " IS NOT NULL", null, null, null, null); 17486802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Set<Long> usedPhotoFileIds = Sets.newHashSet(); 17496802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> photoFileIdToDataId = Maps.newHashMap(); 1750f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 1751f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro while (c.moveToNext()) { 17526802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long dataId = c.getLong(0); 17536802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long photoFileId = c.getLong(1); 17546802030a777c0c3ba1dc029c534cca4784260632Dave Santoro usedPhotoFileIds.add(photoFileId); 17556802030a777c0c3ba1dc029c534cca4784260632Dave Santoro photoFileIdToDataId.put(photoFileId, dataId); 17566802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 17576802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } finally { 17586802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.close(); 17596802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 17606802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 17616802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Also query for all social stream item photos. 1762c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro c = db.query(Tables.STREAM_ITEM_PHOTOS + " JOIN " + Tables.STREAM_ITEMS 1763c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " ON " + StreamItemPhotos.STREAM_ITEM_ID + "=" + StreamItemsColumns.CONCRETE_ID 1764c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " JOIN " + Tables.RAW_CONTACTS 1765c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " ON " + StreamItems.RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID, 17666802030a777c0c3ba1dc029c534cca4784260632Dave Santoro new String[]{ 1767c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotosColumns.CONCRETE_ID, 1768c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID, 1769c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotos.PHOTO_FILE_ID, 1770c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro RawContacts.ACCOUNT_TYPE, 1771c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro RawContacts.ACCOUNT_NAME 17726802030a777c0c3ba1dc029c534cca4784260632Dave Santoro }, 17736802030a777c0c3ba1dc029c534cca4784260632Dave Santoro null, null, null, null, null); 17746802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> photoFileIdToStreamItemPhotoId = Maps.newHashMap(); 17756802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> streamItemPhotoIdToStreamItemId = Maps.newHashMap(); 1776c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Map<Long, Account> streamItemPhotoIdToAccount = Maps.newHashMap(); 17776802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 17786802030a777c0c3ba1dc029c534cca4784260632Dave Santoro while (c.moveToNext()) { 17796802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemPhotoId = c.getLong(0); 17806802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemId = c.getLong(1); 17816802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long photoFileId = c.getLong(2); 1782c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro String accountType = c.getString(3); 1783c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro String accountName = c.getString(4); 17846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro usedPhotoFileIds.add(photoFileId); 17856802030a777c0c3ba1dc029c534cca4784260632Dave Santoro photoFileIdToStreamItemPhotoId.put(photoFileId, streamItemPhotoId); 17866802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemPhotoIdToStreamItemId.put(streamItemPhotoId, streamItemId); 1787c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Account account = new Account(accountName, accountType); 1788c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro streamItemPhotoIdToAccount.put(photoFileId, account); 1789f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1790f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 1791f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 1792f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1793f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1794f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Run the photo store cleanup. 17955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> missingPhotoIds = mPhotoStore.get().cleanup(usedPhotoFileIds); 1796f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1797d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro // If any of the keys we're using no longer exist, clean them up. We need to do these 1798d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro // using internal APIs or direct DB access to avoid permission errors. 17996802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (!missingPhotoIds.isEmpty()) { 1800f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 1801d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro db.beginTransactionWithListener(this); 1802d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro for (long missingPhotoId : missingPhotoIds) { 1803d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro if (photoFileIdToDataId.containsKey(missingPhotoId)) { 1804d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro long dataId = photoFileIdToDataId.get(missingPhotoId); 1805d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro ContentValues updateValues = new ContentValues(); 1806d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro updateValues.putNull(Photo.PHOTO_FILE_ID); 1807d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro updateData(ContentUris.withAppendedId(Data.CONTENT_URI, dataId), 1808d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro updateValues, null, null, false); 1809d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro } 1810d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro if (photoFileIdToStreamItemPhotoId.containsKey(missingPhotoId)) { 1811d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro // For missing photos that were in stream item photos, just delete the 1812d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro // stream item photo. 1813d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro long streamItemPhotoId = photoFileIdToStreamItemPhotoId.get(missingPhotoId); 1814d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro db.delete(Tables.STREAM_ITEM_PHOTOS, StreamItemPhotos._ID + "=?", 1815d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro new String[]{String.valueOf(streamItemPhotoId)}); 1816d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro } 1817d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro } 1818d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro db.setTransactionSuccessful(); 1819d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro } catch (Exception e) { 1820d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro // Cleanup failure is not a fatal problem. We'll try again later. 1821d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro Log.e(TAG, "Failed to clean up outdated photo references", e); 1822d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro } finally { 1823d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro db.endTransaction(); 1824f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1825f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1826f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1827f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 18286efb7db26598b105342d02207e0ca1c8725c10daDave Santoro @Override 1829b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1830b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 183131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 183231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 18336efb7db26598b105342d02207e0ca1c8725c10daDave Santoro @Override 18346efb7db26598b105342d02207e0ca1c8725c10daDave Santoro protected ThreadLocal<ContactsTransaction> getTransactionHolder() { 18356efb7db26598b105342d02207e0ca1c8725c10daDave Santoro return mTransactionHolder; 18366efb7db26598b105342d02207e0ca1c8725c10daDave Santoro } 18376efb7db26598b105342d02207e0ca1c8725c10daDave Santoro 18385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public ProfileProvider getProfileProvider() { 18395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return new ProfileProvider(this); 18405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 18415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1842524913c66ce75ca8dec127ac88e3bc2249c246d9Dave Santoro @VisibleForTesting 1843f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /* package */ PhotoStore getPhotoStore() { 18445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mContactsPhotoStore; 1845f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1846f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1847d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro @VisibleForTesting 1848d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro /* package */ PhotoStore getProfilePhotoStore() { 1849d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro return mProfilePhotoStore; 1850d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro } 1851d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro 185287614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro /* package */ int getMaxDisplayPhotoDim() { 185387614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro return mMaxDisplayPhotoDim; 185487614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro } 185587614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro 185687614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro /* package */ int getMaxThumbnailPhotoDim() { 185787614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro return mMaxThumbnailPhotoDim; 185887614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro } 185987614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro 1860013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1861013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1862013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1863013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 18645df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov /* package */ NameLookupBuilder getNameLookupBuilder() { 18655df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov return mNameLookupBuilder; 18665df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov } 18675df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov 18685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 1869ed78fd6df5e9f3a2d572162e5d374d1f4a625bddDmitri Plotnikov public ContactDirectoryManager getContactDirectoryManagerForTest() { 187072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return mContactDirectoryManager; 187172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 187272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 187372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 18745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 18755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 18765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 18775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 18785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean inProfileMode() { 18795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Boolean profileMode = mInProfileMode.get(); 18805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return profileMode != null && profileMode; 18815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 18825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 18833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 18845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int version = Integer.parseInt( 18855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 1886b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 18873d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18883d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1889568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1890568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1891568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1892568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1893568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1894bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Imports legacy contacts as a background task. 1895568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1896bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private void importLegacyContactsInBackground() { 1897bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 1898bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 1899568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1900bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 19015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setLocale(this, mCurrentLocale); 1902bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 1903568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1904bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1905bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (importLegacyContacts(importer)) { 1906bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportSuccess(); 1907bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } else { 1908bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportFailure(); 1909bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1910568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1911568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1912bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1913bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 1914bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1915bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 1916bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1917bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 1918bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 1919bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1920b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 19215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 1922b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 1923bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 1924bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 1925bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1926bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1927bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1928bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 1929bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1930bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 1931bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 1932bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1933bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 1934bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1935bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 1936bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 1937bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 1938bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 1939bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 1940bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 1941bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 1942bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 1943bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 1944bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1945bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 1946bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1947bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 1948bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 1949bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1950bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // Do not let any database changes until this issue is resolved. 1951bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mOkToOpenAccess = false; 19523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19533d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 19543d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1955568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 19560e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 19573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 19583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 1959bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 1960bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1961bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1962bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 1963bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 1964bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 19653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 19663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 19673d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1968bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 1969bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 19703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19713d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1972a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1973a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1974a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1975a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 19765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.wipeData(); 19775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper.wipeData(); 19785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore.clear(); 19795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore.clear(); 19803826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS; 1981a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1982a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1983568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 198415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov * During intialization, this content provider will 1985568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1986568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1987568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1988568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1989568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 199015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private void waitForAccess(CountDownLatch latch) { 199115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (latch == null) { 199215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 199315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 199415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 199515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov while (true) { 199615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov try { 199715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov latch.await(); 199815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 199915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } catch (InterruptedException e) { 200015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Thread.currentThread().interrupt(); 2001ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2002568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2003568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2004568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 20055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 20065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Determines whether the given URI should be directed to the profile 20075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database rather than the contacts database. This is true under either 20085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * of three conditions: 20095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 1. The URI itself is specifically for the profile. 20105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 2. The URI contains ID references that are in the profile ID-space. 20115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 3. The URI contains lookup key references that match the special profile lookup key. 20125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param uri The URI to examine. 20135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @return Whether to direct the DB operation to the profile database. 20145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 20155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean mapsToProfileDb(Uri uri) { 20165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return sUriMatcher.mapsToProfile(uri); 20175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 20205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Determines whether the given URI with the given values being inserted 20215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * should be directed to the profile database rather than the contacts 20225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database. This is true if the URI already maps to the profile DB from 20235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a call to {@link #mapsToProfileDb} or if the URI matches a URI that 20245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * specifies parent IDs via the ContentValues, and the given ContentValues 20255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * contains an ID in the profile ID-space. 20265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param uri The URI to examine. 20275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param values The values being inserted. 20285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @return Whether to direct the DB insert to the profile database. 20295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 20305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean mapsToProfileDbWithInsertedValues(Uri uri, ContentValues values) { 20315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 20325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return true; 20335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int match = sUriMatcher.match(uri); 20355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (INSERT_URI_ID_VALUE_MAP.containsKey(match)) { 20365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String idField = INSERT_URI_ID_VALUE_MAP.get(match); 20375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (values.containsKey(idField)) { 20385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long id = values.getAsLong(idField); 20395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (ContactsContract.isProfileId(id)) { 20405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return true; 20415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return false; 20455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 20485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Switches the provider's thread-local context variables to prepare for performing 20495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a profile operation. 20505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 20516efb7db26598b105342d02207e0ca1c8725c10daDave Santoro protected void switchToProfileMode() { 20525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mProfileHelper); 20535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.set(mProfileTransactionContext); 20545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.set(mProfileAggregator); 20555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mPhotoStore.set(mProfilePhotoStore); 20565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mInProfileMode.set(true); 20575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 20605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Switches the provider's thread-local context variables to prepare for performing 20615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a contacts operation. 20625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 20636efb7db26598b105342d02207e0ca1c8725c10daDave Santoro protected void switchToContactMode() { 20645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mContactsHelper); 20655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.set(mContactTransactionContext); 20665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.set(mContactAggregator); 20675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mPhotoStore.set(mContactsPhotoStore); 20685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mInProfileMode.set(false); 20695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 207036aa19fbab3722288b7f0917166ef6990ab7b52cDave Santoro // Clear out the active database; modification operations will set this to the contacts DB. 207136aa19fbab3722288b7f0917166ef6990ab7b52cDave Santoro mActiveDb.set(null); 20725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 2074568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2075568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 207615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 207736612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro 207836612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro // Enforce stream items access check if applicable. 207936612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro enforceSocialStreamWritePermission(uri); 208036612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro 20815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDbWithInsertedValues(uri, values)) { 2082078f588cef389358adabc579de00747878f3c108Dave Santoro switchToProfileMode(); 2083078f588cef389358adabc579de00747878f3c108Dave Santoro return mProfileProvider.insert(uri, values); 20845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 20855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 20865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.insert(uri, values); 20875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2088568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2089568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2090568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2091568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 209215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (mWriteAccessLatch != null) { 2093bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 2094bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 2095bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 2096bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 2097bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (match == PROVIDER_STATUS) { 2098bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 2099bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 2100bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 2101bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 2102bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2103bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 2104bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2105bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2106bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 210715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 210836612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro 210936612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro // Enforce stream items access check if applicable. 211036612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro enforceSocialStreamWritePermission(uri); 211136612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro 21125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 2113078f588cef389358adabc579de00747878f3c108Dave Santoro switchToProfileMode(); 2114078f588cef389358adabc579de00747878f3c108Dave Santoro return mProfileProvider.update(uri, values, selection, selectionArgs); 21155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 21165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 21175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.update(uri, values, selection, selectionArgs); 21185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2119568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2120568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2121568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2122568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 212315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 212436612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro 212536612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro // Enforce stream items access check if applicable. 212636612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro enforceSocialStreamWritePermission(uri); 212736612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro 21285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 2129078f588cef389358adabc579de00747878f3c108Dave Santoro switchToProfileMode(); 2130078f588cef389358adabc579de00747878f3c108Dave Santoro return mProfileProvider.delete(uri, selection, selectionArgs); 21315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 21325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 21335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.delete(uri, selection, selectionArgs); 21345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 21375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 21385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Replaces the current (thread-local) database to use for the operation with the given one. 21395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param db The database to use. 21405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 21415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /* package */ void substituteDb(SQLiteDatabase db) { 21425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 2143568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2144568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2145568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 214682792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro public Bundle call(String method, String arg, Bundle extras) { 214782792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro waitForAccess(mReadAccessLatch); 214882792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro if (method.equals(Authorization.AUTHORIZATION_METHOD)) { 214982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro Uri uri = (Uri) extras.getParcelable(Authorization.KEY_URI_TO_AUTHORIZE); 215082792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 215182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // Check permissions on the caller. The URI can only be pre-authorized if the caller 215282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // already has the necessary permissions. 215382792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro enforceSocialStreamReadPermission(uri); 215482792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro if (mapsToProfileDb(uri)) { 215582792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro mProfileProvider.enforceReadPermission(uri); 215682792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro } 215782792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 215882792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // If there hasn't been a security violation yet, we're clear to pre-authorize the URI. 215982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro Uri authUri = preAuthorizeUri(uri); 216082792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro Bundle response = new Bundle(); 216182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro response.putParcelable(Authorization.KEY_AUTHORIZED_URI, authUri); 216282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro return response; 216382792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro } 216482792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro return null; 216582792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro } 216682792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 216782792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro /** 216882792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * Pre-authorizes the given URI, adding an expiring permission token to it and placing that 216982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * in our map of pre-authorized URIs. 217082792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * @param uri The URI to pre-authorize. 217182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * @return A pre-authorized URI that will not require special permissions to use. 217282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro */ 217382792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro private Uri preAuthorizeUri(Uri uri) { 217482792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro String token = String.valueOf(mRandom.nextLong()); 217582792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro Uri authUri = uri.buildUpon() 217682792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro .appendQueryParameter(PREAUTHORIZED_URI_TOKEN, token) 217782792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro .build(); 217882792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro long expiration = SystemClock.elapsedRealtime() + mPreAuthorizedUriDuration; 217982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro mPreAuthorizedUris.put(authUri, expiration); 218082792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 218182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro return authUri; 218282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro } 218382792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 218482792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro /** 218582792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * Checks whether the given URI has an unexpired permission token that would grant access to 218682792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * query the content. If it does, the regular permission check should be skipped. 218782792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * @param uri The URI being accessed. 218882792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro * @return Whether the URI is a pre-authorized URI that is still valid. 218982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro */ 219082792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro public boolean isValidPreAuthorizedUri(Uri uri) { 219182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // Only proceed if the URI has a permission token parameter. 219282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro if (uri.getQueryParameter(PREAUTHORIZED_URI_TOKEN) != null) { 219382792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // First expire any pre-authorization URIs that are no longer valid. 219482792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro long now = SystemClock.elapsedRealtime(); 219582792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro Set<Uri> expiredUris = Sets.newHashSet(); 219682792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro for (Uri preAuthUri : mPreAuthorizedUris.keySet()) { 219782792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro if (mPreAuthorizedUris.get(preAuthUri) < now) { 219882792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro expiredUris.add(preAuthUri); 219982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro } 220082792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro } 220182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro for (Uri expiredUri : expiredUris) { 220282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro mPreAuthorizedUris.remove(expiredUri); 220382792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro } 220482792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 220582792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // Now check to see if the pre-authorized URI map contains the URI. 220682792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro if (mPreAuthorizedUris.containsKey(uri)) { 220782792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // Unexpired token - skip the permission check. 220882792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro return true; 220982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro } 221082792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro } 221182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro return false; 221282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro } 221382792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro 221482792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro @Override 2215078f588cef389358adabc579de00747878f3c108Dave Santoro protected boolean yield(ContactsTransaction transaction) { 2216078f588cef389358adabc579de00747878f3c108Dave Santoro // If there's a profile transaction in progress, and we're yielding, we need to 2217078f588cef389358adabc579de00747878f3c108Dave Santoro // end it. Unlike the Contacts DB yield (which re-starts a transaction at its 2218078f588cef389358adabc579de00747878f3c108Dave Santoro // conclusion), we can just go back into a state in which we have no active 2219078f588cef389358adabc579de00747878f3c108Dave Santoro // profile transaction, and let it be re-created as needed. We can't hold onto 2220078f588cef389358adabc579de00747878f3c108Dave Santoro // the transaction without risking a deadlock. 2221078f588cef389358adabc579de00747878f3c108Dave Santoro SQLiteDatabase profileDb = transaction.removeDbForTag(PROFILE_DB_TAG); 2222078f588cef389358adabc579de00747878f3c108Dave Santoro if (profileDb != null) { 2223078f588cef389358adabc579de00747878f3c108Dave Santoro profileDb.setTransactionSuccessful(); 2224078f588cef389358adabc579de00747878f3c108Dave Santoro profileDb.endTransaction(); 2225078f588cef389358adabc579de00747878f3c108Dave Santoro } 2226078f588cef389358adabc579de00747878f3c108Dave Santoro 2227078f588cef389358adabc579de00747878f3c108Dave Santoro // Now proceed with the Contacts DB yield. 2228078f588cef389358adabc579de00747878f3c108Dave Santoro SQLiteDatabase contactsDb = transaction.getDbForTag(CONTACTS_DB_TAG); 2229078f588cef389358adabc579de00747878f3c108Dave Santoro return contactsDb != null && contactsDb.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY); 2230078f588cef389358adabc579de00747878f3c108Dave Santoro } 2231078f588cef389358adabc579de00747878f3c108Dave Santoro 2232078f588cef389358adabc579de00747878f3c108Dave Santoro @Override 2233568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2234568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 223515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 2236078f588cef389358adabc579de00747878f3c108Dave Santoro return super.applyBatch(operations); 2237568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2238568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 22394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 22407b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov public int bulkInsert(Uri uri, ContentValues[] values) { 22417b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov waitForAccess(mWriteAccessLatch); 2242078f588cef389358adabc579de00747878f3c108Dave Santoro return super.bulkInsert(uri, values); 22437b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov } 22447b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov 22457b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov @Override 2246078f588cef389358adabc579de00747878f3c108Dave Santoro public void onBegin() { 2247bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2248b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 2249b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 22505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (inProfileMode()) { 22515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator.clearPendingAggregations(); 22525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileTransactionContext.clear(); 22535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 22545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator.clearPendingAggregations(); 22555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactTransactionContext.clear(); 22565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2257b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2258b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2259285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2260078f588cef389358adabc579de00747878f3c108Dave Santoro public void onCommit() { 2261bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2262b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2263b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2264b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 22655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateInTransaction(mTransactionContext.get(), mActiveDb.get()); 22661a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 22671a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 22685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateAllVisible(); 22691a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 22703826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2271bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 2272bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 22733826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatusUpdateNeeded) { 22743826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 22753826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = false; 22763826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 2277b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2278b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2279078f588cef389358adabc579de00747878f3c108Dave Santoro @Override 2280078f588cef389358adabc579de00747878f3c108Dave Santoro public void onRollback() { 2281078f588cef389358adabc579de00747878f3c108Dave Santoro // Not used. 2282078f588cef389358adabc579de00747878f3c108Dave Santoro } 2283078f588cef389358adabc579de00747878f3c108Dave Santoro 2284bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov private void updateSearchIndexInTransaction() { 22855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> staleContacts = mTransactionContext.get().getStaleSearchIndexContactIds(); 22865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> staleRawContacts = mTransactionContext.get().getStaleSearchIndexRawContactIds(); 2287bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov if (!staleContacts.isEmpty() || !staleRawContacts.isEmpty()) { 2288bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mSearchIndexManager.updateIndexForRawContacts(staleContacts, staleRawContacts); 22895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().clearSearchIndexUpdates(); 2290bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 2291bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 2292bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 2293b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2294bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2295b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2296b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 22971129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 22985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro for (long rawContactId : mTransactionContext.get().getInsertedRawContactIds()) { 22995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateRawContactDisplayName(mActiveDb.get(), rawContactId); 23005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().onRawContactInsert(mTransactionContext.get(), mActiveDb.get(), 23015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro rawContactId); 230224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 230324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 23045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> dirtyRawContacts = mTransactionContext.get().getDirtyRawContactIds(); 2305d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!dirtyRawContacts.isEmpty()) { 2306a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2307a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2308d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, dirtyRawContacts); 2309a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 23105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(mSb.toString()); 2311a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2312a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 23135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> updatedRawContacts = mTransactionContext.get().getUpdatedRawContactIds(); 2314d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!updatedRawContacts.isEmpty()) { 2315a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2316a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2317d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, updatedRawContacts); 2318a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 23195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(mSb.toString()); 2320b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2321b5a4add17815167d20a90645779df34cdf45280dFred Quintana 23225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Update sync states. 23235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro for (Map.Entry<Long, Object> entry : mTransactionContext.get().getUpdatedSyncStates()) { 2324b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 23255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().getSyncState().update(mActiveDb.get(), id, entry.getValue()) <= 0) { 23269d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 23279d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 23289d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 2329b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2330b5a4add17815167d20a90645779df34cdf45280dFred Quintana 23315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().clear(); 2332b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2333b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2334a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2335a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2336a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2337a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2338d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private void appendIds(StringBuilder sb, Set<Long> ids) { 2339b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2340a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2341b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2342a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2343a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2344285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2345285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2346285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2347cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 234881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 234981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 235081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 235181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 235281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 235381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 235481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2355cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2356568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 235751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 23583826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != status) { 23593826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = status; 23603826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov getContext().getContentResolver().notifyChange(ProviderStatus.CONTENT_URI, null, false); 23613826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 236251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 236351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2364f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public DataRowHandler getDataRowHandler(final String mimeType) { 23655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (inProfileMode()) { 23665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return getDataRowHandlerForProfile(mimeType); 23675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 23693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 23706d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov handler = new DataRowHandlerForCustomMimetype( 23715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro getContext(), mContactsHelper, mContactAggregator, mimeType); 23723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 23733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 23753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 23775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public DataRowHandler getDataRowHandlerForProfile(final String mimeType) { 23785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro DataRowHandler handler = mProfileDataRowHandlers.get(mimeType); 23795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (handler == null) { 23805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handler = new DataRowHandlerForCustomMimetype( 23815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro getContext(), mProfileHelper, mProfileAggregator, mimeType); 23825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDataRowHandlers.put(mimeType, handler); 23835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return handler; 23855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 23874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2388de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2389bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 23901129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2391b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2392f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 23935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 23945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 2395078f588cef389358adabc579de00747878f3c108Dave Santoro mActiveDb.set(mContactsHelper.getWritableDatabase()); 23965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 2398f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2399f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2400f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2401a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2402a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 240335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2404a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 240535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 24065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 24075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mDbHelper.get().getSyncState().insert(mActiveDb.get(), values); 240835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 240935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2410d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2411d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 24126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 24136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 24146bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 241524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 241624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro throw new UnsupportedOperationException( 241724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "The profile contact is created automatically"); 241824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 241924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 2420d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 2421d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 24225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = insertRawContact(uri, values, callerIsSyncAdapter); 2423f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2424a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2425a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2426a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2427d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 2428d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 2429d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 2430d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(segment)); 2431f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2432f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2433a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2434a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2435a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 24373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItems.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 24383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 24393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24430c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 24440c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 2445f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2446f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2447a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2448a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2449a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2450ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2451f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2452f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2453ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2454ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2455ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2456eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 24575aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 245843880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2459eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2460eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2461eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 24625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 24635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 246482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 24651f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 24661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24671f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 24683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 24693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 24703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 24753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 24763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 24813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItemPhotos.STREAM_ITEM_ID, uri.getPathSegments().get(1)); 24823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 24833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 2487a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 248881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2489f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2490a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2491a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 24937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 24947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2496de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2497a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2498a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2499a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2500e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2501e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2502e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2503e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2504e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2505e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2506e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2507e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2508e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2509e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2510e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2511e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2512e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 25137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2514e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2515f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2516f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2517e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2518f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2519f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2520f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2521e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2522e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2523e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2524e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2525e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 25265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 2527fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 2528e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2529e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2530e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2531e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2532e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2533e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2534e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2535e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2536e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2537e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2538e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2539e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 25405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 2541fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 2542e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2543e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2544e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2545f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2546f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2547e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2548f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2549f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2550e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2551e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2552f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2553f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2554e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2555f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2556f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2557f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2558f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2559035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2560f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2561e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 25627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 256543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Resolves the account and builds an {@link AccountWithDataSet} based on the data set specified 256643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * in the URI or values (if any). 256743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * @param uri Current {@link Uri} being operated on. 256843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * @param values {@link ContentValues} to read and possibly update. 256943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro */ 257043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private AccountWithDataSet resolveAccountWithDataSet(Uri uri, ContentValues values) { 25713593682b8d9213fde576a0cff54458ad50563980Dave Santoro final Account account = resolveAccount(uri, values); 257243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = null; 257343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (account != null) { 257443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 257543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (dataSet == null) { 25763593682b8d9213fde576a0cff54458ad50563980Dave Santoro dataSet = values.getAsString(RawContacts.DATA_SET); 2577a71dc460ca951c7aca591f3f470c160cde70a1e3Dave Santoro } else { 25783593682b8d9213fde576a0cff54458ad50563980Dave Santoro values.put(RawContacts.DATA_SET, dataSet); 257943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 258043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet = new AccountWithDataSet(account.name, account.type, dataSet); 258143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 258243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro return accountWithDataSet; 258343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 258443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 258543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro /** 2586d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 25876bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 25886bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 25896bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 25906bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2591d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2592de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 25936bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 25946bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 25956bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 259624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Inserts an item in the raw contacts table 2597a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2598f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2599f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2600dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param callerIsSyncAdapter 2601a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2602a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 26035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private long insertRawContact(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2604f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2605f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2606f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2607f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 260843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = resolveAccountWithDataSet(uri, mValues); 26097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26103d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 26113d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2612f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 26133d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 26143d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 26155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long rawContactId = mActiveDb.get().insert(Tables.RAW_CONTACTS, 26165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro RawContacts.CONTACT_ID, mValues); 2617f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 26185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 2619f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 2620f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 26215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markNewForAggregation(rawContactId, aggregationMode); 2622285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 26235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Trigger creation of a Contact based on this RawContact at the end of transaction 26245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactInserted(rawContactId, accountWithDataSet); 2625f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2626dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 2627dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 2628dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long starred = values.getAsLong(RawContacts.STARRED); 2629dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (starred != null && starred != 0) { 2630dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred != 0); 2631dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2632dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2633dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 26343826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 2635023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2636a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2637a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2638dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void addAutoAddMembership(long rawContactId) { 2639dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID, 2640dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2641dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2642dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2643dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2644dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2645dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2646dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private Long findGroupByRawContactId(String selection, long rawContactId) { 26475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS + "," + Tables.RAW_CONTACTS, 26485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROJECTION_GROUP_ID, selection, 2649dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}, 2650dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana null /* groupBy */, null /* having */, null /* orderBy */); 2651dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 2652dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 2653dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return c.getLong(0); 2654dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2655dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return null; 2656dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2657dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 2658dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2659dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2660dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2661dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateFavoritesMembership(long rawContactId, boolean isStarred) { 2662dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID, 2663dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2664dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2665dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (isStarred) { 2666dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2667dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2668dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana deleteDataGroupMembership(rawContactId, groupId); 2669dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2670dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2671dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2672dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2673dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void insertDataGroupMembership(long rawContactId, long groupId) { 2674dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues groupMembershipValues = new ContentValues(); 2675dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.GROUP_ROW_ID, groupId); 2676dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 2677dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(DataColumns.MIMETYPE_ID, 26785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 26795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().insert(Tables.DATA, null, groupMembershipValues); 2680dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2681dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2682dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void deleteDataGroupMembership(long rawContactId, long groupId) { 2683dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final String[] selectionArgs = { 26845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Long.toString(mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)), 2685dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(groupId), 2686dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(rawContactId)}; 26875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs); 2688dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2689dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2690a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2691a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2692a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2693a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2694a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2695a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2696f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2697a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2698de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2699de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 270067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2701de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 270220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2703de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2704de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2705de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 27065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 2707de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2708de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2709508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2710de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2711de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2712de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2713de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2714de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 27154097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 27165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.get().getMimeTypeId(mimeType)); 2717de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2718a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2719a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 27205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = rowHandler.insert(mActiveDb.get(), mTransactionContext.get(), rawContactId, mValues); 2721f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 27225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 2723a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 27245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactUpdated(rawContactId); 2725a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 27264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27274f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 27283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_items table. The account is checked against the 27303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account in the raw contact for which the stream item is being inserted. If the 27313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * new stream item results in more stream items under this raw contact than the limit, 27323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest one will be deleted (note that if the stream item inserted was the 27333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * oldest, it will be immediately deleted, and this will return 0). 27343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 27353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 27363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 27373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return the stream item _ID of the newly created row, or 0 if it was not created 27383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 27393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItem(Uri uri, ContentValues values) { 27403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 27413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 27423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 27433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = mValues.getAsLong(StreamItems.RAW_CONTACT_ID); 27453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 27473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 27483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 27493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27506802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to insert accounts params - they don't exist in the stream items table. 27516802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_NAME); 27526802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_TYPE); 27536802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 27543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Insert the new stream item. 27555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mActiveDb.get().insert(Tables.STREAM_ITEMS, null, mValues); 27566802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (id == -1) { 27576802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Insertion failed. 27586802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return 0; 27596802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check to see if we're over the limit for stream items under this raw contact. 27623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // It's possible that the inserted stream item is older than the the existing 27633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // ones, in which case it may be deleted immediately (resetting the ID to 0). 27643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = cleanUpOldStreamItems(rawContactId, id); 27653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 27673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_item_photos table. The account is checked against 27713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the account in the raw contact that owns the stream item being modified. 27723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 27733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 27743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 27756802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @return the stream item photo _ID of the newly created row, or 0 if there was an issue 27766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * with processing the photo or creating the row 27773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 27783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItemPhoto(Uri uri, ContentValues values) { 27793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 27803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 27813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 27823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = mValues.getAsLong(StreamItemPhotos.STREAM_ITEM_ID); 27843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemId != 0) { 27853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = lookupRawContactIdForStreamId(streamItemId); 27863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 27883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 27893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 27903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27916802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to insert accounts params - they don't exist in the stream item 27926802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // photos table. 27936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_NAME); 27946802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_TYPE); 27953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo and store it. 27976802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (processStreamItemPhoto(mValues, false)) { 27986802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Insert the stream item photo. 27995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mActiveDb.get().insert(Tables.STREAM_ITEM_PHOTOS, null, mValues); 28006802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 28033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 28066802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * Processes the photo contained in the {@link ContactsContract.StreamItemPhotos#PHOTO} 28076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * field of the given values, attempting to store it in the photo store. If successful, 28086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * the resulting photo file ID will be added to the values for insert/update in the table. 28096802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * <p> 28106802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * If updating, it is valid for the picture to be empty or unspecified (the function will 28116802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * still return true). If inserting, a valid picture must be specified. 28126802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @param values The content values provided by the caller. 28136802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @param forUpdate Whether this photo is being processed for update (vs. insert). 28146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @return Whether the insert or update should proceed. 28156802030a777c0c3ba1dc029c534cca4784260632Dave Santoro */ 28166802030a777c0c3ba1dc029c534cca4784260632Dave Santoro private boolean processStreamItemPhoto(ContentValues values, boolean forUpdate) { 28176802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (!values.containsKey(StreamItemPhotos.PHOTO)) { 28186802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return forUpdate; 28196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro byte[] photoBytes = values.getAsByteArray(StreamItemPhotos.PHOTO); 28216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoBytes == null) { 28226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return forUpdate; 28236802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28246802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 28256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo and store it. 28266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 28275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long photoFileId = mPhotoStore.get().insert(new PhotoProcessor(photoBytes, 28281dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim, true), true); 28296802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileId != 0) { 28306802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.put(StreamItemPhotos.PHOTO_FILE_ID, photoFileId); 28316802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(StreamItemPhotos.PHOTO); 28326802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return true; 28336802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 28346802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Couldn't store the photo, return 0. 28356802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Log.e(TAG, "Could not process stream item photo for insert"); 28366802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return false; 28376802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28386802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } catch (IOException ioe) { 28396802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Log.e(TAG, "Could not process stream item photo for insert", ioe); 28406802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return false; 28416802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28426802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28436802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 28446802030a777c0c3ba1dc029c534cca4784260632Dave Santoro /** 28453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Looks up the raw contact ID that owns the specified stream item. 28463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param streamItemId The ID of the stream item. 28473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The associated raw contact ID, or -1 if no such stream item exists. 28483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long lookupRawContactIdForStreamId(long streamItemId) { 28503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = -1; 28515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, 28525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{StreamItems.RAW_CONTACT_ID}, 28533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems._ID + "=?", new String[]{String.valueOf(streamItemId)}, 28543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c.moveToFirst()) { 28573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann rawContactId = c.getLong(0); 28583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 28603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 28613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return rawContactId; 28633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 286636612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro * If the given URI is reading stream items or stream photos, this will run a permission check 286736612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro * for the android.permission.READ_SOCIAL_STREAM permission - otherwise it will do nothing. 286836612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro * @param uri The URI to check. 286936612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro */ 287036612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro private void enforceSocialStreamReadPermission(Uri uri) { 287182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro if (SOCIAL_STREAM_URIS.contains(sUriMatcher.match(uri)) 287282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro && !isValidPreAuthorizedUri(uri)) { 287336612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro getContext().enforceCallingOrSelfPermission( 287436612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro "android.permission.READ_SOCIAL_STREAM", null); 287536612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro } 287636612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro } 287736612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro 287836612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro /** 287936612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro * If the given URI is modifying stream items or stream photos, this will run a permission check 288036612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro * for the android.permission.WRITE_SOCIAL_STREAM permission - otherwise it will do nothing. 288136612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro * @param uri The URI to check. 288236612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro */ 288336612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro private void enforceSocialStreamWritePermission(Uri uri) { 288436612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro if (SOCIAL_STREAM_URIS.contains(sUriMatcher.match(uri))) { 288536612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro getContext().enforceCallingOrSelfPermission( 288636612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro "android.permission.WRITE_SOCIAL_STREAM", null); 288736612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro } 288836612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro } 288936612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro 289036612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro /** 28913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given raw contact ID is owned by the given account. 28923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account is null, this will return true iff the raw contact 28933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * is also associated with the "null" account. 28943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 28953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account does not match, this will throw a security exception. 28963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 28973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to check for. 28983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void enforceModifyingAccount(Account account, long rawContactId) { 29003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String accountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 29013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + "=? AND " 29023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + "=?"; 29033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String noAccountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 29043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL AND " 29053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL"; 29063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c; 29073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (account != null) { 29085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c = mActiveDb.get().query(Tables.RAW_CONTACTS, 29095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{RawContactsColumns.CONCRETE_ID}, accountSelection, 29103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(rawContactId), mAccount.name, mAccount.type}, 29113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 29123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 29135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c = mActiveDb.get().query(Tables.RAW_CONTACTS, 29145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{RawContactsColumns.CONCRETE_ID}, noAccountSelection, 29155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{String.valueOf(rawContactId)}, 29163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 29173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if(c.getCount() == 0) { 29203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann throw new SecurityException("Caller account does not match raw contact ID " 29213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + rawContactId); 29223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream items matches up with the given 29303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 29313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 29323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 29333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 29343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 29353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item IDs that would be included in this selection. 29363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItems(Account account, String selection, 29383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 29393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = Lists.newArrayList(); 29403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 29413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 29425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), 29433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{StreamItems._ID, StreamItems.RAW_CONTACT_ID}, 29443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 29453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 29473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemIds.add(c.getLong(0)); 29483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 29503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 29513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds; 29563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream item photos matches up with the given 29603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 29613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 29623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 29633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 29643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 29653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item photo IDs that would be included in this selection. 29663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItemPhotos(Account account, String selection, 29683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 29693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemPhotoIds = Lists.newArrayList(); 29703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 29713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 29725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), 29735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{StreamItemPhotos._ID, StreamItems.RAW_CONTACT_ID}, 29743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 29753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 29773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemPhotoIds.add(c.getLong(0)); 29783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 29803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 29813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemPhotoIds; 29863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Queries the database for stream items under the given raw contact. If there are 29903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * more entries than {@link ContactsProvider2#MAX_STREAM_ITEMS_PER_RAW_CONTACT}, 29913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest entries (as determined by timestamp) will be deleted. 29923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to examine for stream items. 29933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param insertedStreamItemId The ID of the stream item that was just inserted, 29943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * prompting this cleanup. Callers may pass 0 if no insertion prompted the 29953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * cleanup. 29963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The ID of the inserted stream item if it still exists after cleanup; 29973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 0 otherwise. 29983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long cleanUpOldStreamItems(long rawContactId, long insertedStreamItemId) { 30003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long postCleanupInsertedStreamId = insertedStreamItemId; 30015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, new String[]{StreamItems._ID}, 30023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 30033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, StreamItems.TIMESTAMP + " DESC, " + StreamItems._ID + " DESC"); 30043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 30053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int streamItemCount = c.getCount(); 30063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemCount <= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 30073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Still under the limit - nothing to clean up! 30083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return insertedStreamItemId; 30093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 30103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToLast(); 30113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.getPosition() >= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 30123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = c.getLong(0); 30133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (insertedStreamItemId == streamItemId) { 30143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // The stream item just inserted is being deleted. 30153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann postCleanupInsertedStreamId = 0; 30163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 30173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(c.getLong(0)); 30183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToPrevious(); 30193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 30203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 30213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 30223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 30233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 30243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return postCleanupInsertedStreamId; 30253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 30263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 30279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 302820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 302920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 3030f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 303120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 303220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3033de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3034de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 30350c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro Uri dataUri = inProfileMode() 30360c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro ? Uri.withAppendedPath(Profile.CONTENT_URI, RawContacts.Data.CONTENT_DIRECTORY) 30370c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro : Data.CONTENT_URI; 30380c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro Cursor c = query(dataUri, DataRowHandler.DataDeleteQuery.COLUMNS, 3039f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 3040de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 3041de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 3042f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID); 3043f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 3044a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 30455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count += rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c); 3046f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 30475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 304888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 304920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 305020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 3051de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 305220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 305320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 305420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 305520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 305620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 305788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 305888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 305988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 306020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 3061f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 306288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 306388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 30644da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 3065f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, Data._ID + "=?", 30664da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 3067f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 306820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 306920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 307020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 307120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 307220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3073f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 307420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 307520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 307620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 307720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 307820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 307920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 308020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 308120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 308220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 30837a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 308420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 308520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3086a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 30875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c); 308820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 308920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 309020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 309120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 309220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 309320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 3094ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 3095ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 3096f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 3097f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 3098f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 3099f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 31003593682b8d9213fde576a0cff54458ad50563980Dave Santoro final AccountWithDataSet accountWithDataSet = resolveAccountWithDataSet(uri, mValues); 3101ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3102ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 3103f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 310467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 31055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 310667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 3107f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 3108ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3109dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final boolean isFavoritesGroup = mValues.getAsLong(Groups.FAVORITES) != null 3110dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ? mValues.getAsLong(Groups.FAVORITES) != 0 3111dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana : false; 3112dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3113f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 3114f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 311573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 311673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 31175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long result = mActiveDb.get().insert(Tables.GROUPS, Groups.TITLE, mValues); 3118ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3119dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && isFavoritesGroup) { 3120dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // add all starred raw contacts to this group 3121dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String selection; 3122dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs; 31233593682b8d9213fde576a0cff54458ad50563980Dave Santoro if (accountWithDataSet == null) { 3124dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + " IS NULL AND " 312543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.ACCOUNT_TYPE + " IS NULL AND " 312643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.DATA_SET + " IS NULL"; 3127dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = null; 31283593682b8d9213fde576a0cff54458ad50563980Dave Santoro } else if (accountWithDataSet.getDataSet() == null) { 3129dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + "=? AND " 31303593682b8d9213fde576a0cff54458ad50563980Dave Santoro + RawContacts.ACCOUNT_TYPE + "=? AND " 31313593682b8d9213fde576a0cff54458ad50563980Dave Santoro + RawContacts.DATA_SET + " IS NULL"; 31323593682b8d9213fde576a0cff54458ad50563980Dave Santoro selectionArgs = new String[] { 31333593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountName(), 31343593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountType() 31353593682b8d9213fde576a0cff54458ad50563980Dave Santoro }; 313643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } else { 313743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro selection = RawContacts.ACCOUNT_NAME + "=? AND " 313843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.ACCOUNT_TYPE + "=? AND " 313943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.DATA_SET + "=?"; 31403593682b8d9213fde576a0cff54458ad50563980Dave Santoro selectionArgs = new String[] { 31413593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountName(), 31423593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountType(), 31433593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getDataSet() 31443593682b8d9213fde576a0cff54458ad50563980Dave Santoro }; 3145dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 31465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3147dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{RawContacts._ID, RawContacts.STARRED}, 3148dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, selectionArgs, null, null, null); 3149892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov try { 3150892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov while (c.moveToNext()) { 3151892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (c.getLong(1) != 0) { 3152892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov final long rawContactId = c.getLong(0); 3153892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov insertDataGroupMembership(rawContactId, result); 31545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 3155892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 3156dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3157892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } finally { 3158892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov c.close(); 3159dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3160dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3161dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3162f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 31631a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3164ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 3165ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3166ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 3167ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3168ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31695aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 3170f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // Before inserting, ensure that no settings record already exists for the 3171f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // values being inserted (this used to be enforced by a primary key, but that no 3172f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // longer works with the nullable data_set field added). 3173f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String accountName = values.getAsString(Settings.ACCOUNT_NAME); 3174f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String accountType = values.getAsString(Settings.ACCOUNT_TYPE); 3175f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String dataSet = values.getAsString(Settings.DATA_SET); 3176f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro Uri.Builder settingsUri = Settings.CONTENT_URI.buildUpon(); 3177f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (accountName != null) { 3178f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.ACCOUNT_NAME, accountName); 3179f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3180f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (accountType != null) { 3181f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.ACCOUNT_TYPE, accountType); 3182f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3183f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet != null) { 3184f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.DATA_SET, dataSet); 3185f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3186f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro Cursor c = queryLocal(settingsUri.build(), null, null, null, null, 0); 3187f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro try { 3188f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (c.getCount() > 0) { 31890e21a867a572679d64d79041eb574d13665178d4Dave Santoro // If a record was found, replace it with the new values. 31900e21a867a572679d64d79041eb574d13665178d4Dave Santoro String selection = null; 31910e21a867a572679d64d79041eb574d13665178d4Dave Santoro String[] selectionArgs = null; 31920e21a867a572679d64d79041eb574d13665178d4Dave Santoro if (accountName != null && accountType != null) { 31930e21a867a572679d64d79041eb574d13665178d4Dave Santoro selection = Settings.ACCOUNT_NAME + "=? AND " + Settings.ACCOUNT_TYPE + "=?"; 31940e21a867a572679d64d79041eb574d13665178d4Dave Santoro if (dataSet == null) { 31950e21a867a572679d64d79041eb574d13665178d4Dave Santoro selection += " AND " + Settings.DATA_SET + " IS NULL"; 31960e21a867a572679d64d79041eb574d13665178d4Dave Santoro selectionArgs = new String[] {accountName, accountType}; 31970e21a867a572679d64d79041eb574d13665178d4Dave Santoro } else { 31980e21a867a572679d64d79041eb574d13665178d4Dave Santoro selection += " AND " + Settings.DATA_SET + "=?"; 31990e21a867a572679d64d79041eb574d13665178d4Dave Santoro selectionArgs = new String[] {accountName, accountType, dataSet}; 32000e21a867a572679d64d79041eb574d13665178d4Dave Santoro } 32010e21a867a572679d64d79041eb574d13665178d4Dave Santoro } 32020e21a867a572679d64d79041eb574d13665178d4Dave Santoro return updateSettings(uri, values, selection, selectionArgs); 3203f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3204f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } finally { 3205f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro c.close(); 3206f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3207f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro 3208f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // If we didn't find a duplicate, we're fine to insert. 32095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long id = mActiveDb.get().insert(Tables.SETTINGS, null, values); 32105aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 32111a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 32121a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3213e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 32141a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 3215e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 3216e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3217e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3218ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 321982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 32201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 322182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 322282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 32230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 32244dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 32254dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 32260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 322782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 32284dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 32294dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 32304dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 32314dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 32321f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3234dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 3235dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 323682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 32376802030a777c0c3ba1dc029c534cca4784260632Dave Santoro String accountType = null; 32386802030a777c0c3ba1dc029c534cca4784260632Dave Santoro String accountName = null; 3239f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 32402526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 3241dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 3242dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 3243dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 32442526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 32452526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 32461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 3247dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 3248dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 32490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 32500a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 32510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 32520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3253dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 3254dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 3255dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 32565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String mimeTypeIdIm = String.valueOf(mDbHelper.get().getMimeTypeIdForIm()); 3257dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 32585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String mimeTypeIdEmail = String.valueOf(mDbHelper.get().getMimeTypeIdForEmail()); 3259f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3260f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 3261f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 3262f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 3263f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3264f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 3265f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 32662526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 32672526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 32682526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 32692526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 32702526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32712526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 32722526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32732526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 3274dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32752526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32762526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3277dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32782526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 32792526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 3280dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 32812526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 32822526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 32832526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 32842526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32852526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 32862526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 3287dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32882526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32892526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3290dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 3291dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 329382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 32942526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 32952526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 3296dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 329770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 329870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 32991f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 33001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 33015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cursor = mActiveDb.get().query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 33022526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 33034394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID); 33041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 330567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 33065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 33076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro accountType = cursor.getString(DataContactsQuery.ACCOUNT_TYPE); 33086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro accountName = cursor.getString(DataContactsQuery.ACCOUNT_NAME); 3309e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 33101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 33111f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 33121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 33131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 33141f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 331531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 331631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 331731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 33181f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 33191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 332082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 3321a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 3322a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 3323a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 3324a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 3325a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3326a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3327a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 332882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 3329a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 3330a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 333182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 333282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 333382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 333482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 333582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 3336a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 333782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 333882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 3339aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori mValues.put(StatusUpdates.CHAT_CAPABILITY, 3340aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori values.getAsString(StatusUpdates.CHAT_CAPABILITY)); 33411f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3342a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 33435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().replace(Tables.PRESENCE, null, mValues); 3344a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3345e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 33460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 334782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 334882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 33490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 33500bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Resources resources = getContext().getResources(); 33510bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (!TextUtils.isEmpty(resPackage)) { 33520bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann PackageManager pm = getContext().getPackageManager(); 33530bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann try { 33540bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann resources = pm.getResourcesForApplication(resPackage); 33550bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } catch (NameNotFoundException e) { 33560bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Log.w(TAG, "Contact status update resource package not found: " 33570bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + resPackage); 33580bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33590bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33600bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Integer labelResourceId = values.getAsInteger(StatusUpdates.STATUS_LABEL); 33610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33620bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if ((labelResourceId == null || labelResourceId == 0) && protocol != null) { 33630bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann labelResourceId = Im.getProtocolLabelResource(protocol); 33640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 33650bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann String labelResource = getResourceName(resources, "string", labelResourceId); 33660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33670bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Integer iconResourceId = values.getAsInteger(StatusUpdates.STATUS_ICON); 33680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 33690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33700bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann String iconResource = getResourceName(resources, "drawable", iconResourceId); 33710bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 3372a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 33735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().deleteStatusUpdate(dataId); 3374a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 33756802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 33766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (timestamp != null) { 33775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().replaceStatusUpdate(dataId, timestamp, status, resPackage, 33780bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann iconResourceId, labelResourceId); 33796802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 33805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().insertStatusUpdate(dataId, status, resPackage, iconResourceId, 33810bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann labelResourceId); 33826802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33836802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // For forward compatibility with the new stream item API, insert this status update 33856802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // there as well. If we already have a stream item from this source, update that 33866802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // one instead of inserting a new one (since the semantics of the old status update 33876802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // API is to only have a single record). 33886802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (rawContactId != -1 && !TextUtils.isEmpty(status)) { 33896802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ContentValues streamItemValues = new ContentValues(); 33906802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3391d5ef5903570e533a501abe6a8e3d533fdb5318fcFlavio Lerda // Status updates are text only but stream items are HTML. 3392e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda streamItemValues.put(StreamItems.TEXT, statusUpdateToHtml(status)); 33936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.COMMENTS, ""); 33946802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_PACKAGE, resPackage); 33956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_ICON, iconResource); 33966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_LABEL, labelResource); 33976802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.TIMESTAMP, 33986802030a777c0c3ba1dc029c534cca4784260632Dave Santoro timestamp == null ? System.currentTimeMillis() : timestamp); 33996802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 34006802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Note: The following is basically a workaround for the fact that status 34016802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // updates didn't do any sort of account enforcement, while social stream item 34026802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // updates do. We can't expect callers of the old API to start passing account 34036802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // information along, so we just populate the account params appropriately for 340443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // the raw contact. Data set is not relevant here, as we only check account 340543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // name and type. 34066802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (accountName != null && accountType != null) { 34076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(RawContacts.ACCOUNT_NAME, accountName); 34086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(RawContacts.ACCOUNT_TYPE, accountType); 34096802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 34106802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 34116802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Check for an existing stream item from this source, and insert or update. 34126802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Uri streamUri = StreamItems.CONTENT_URI; 341336612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro Cursor c = queryLocal(streamUri, new String[]{StreamItems._ID}, 34146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro StreamItems.RAW_CONTACT_ID + "=?", 341536612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro new String[]{String.valueOf(rawContactId)}, 341636612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro null, -1 /* directory ID */); 34176802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 34186802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (c.getCount() > 0) { 34196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.moveToFirst(); 342036612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro updateInTransaction(ContentUris.withAppendedId(streamUri, c.getLong(0)), 34216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues, null, null); 34226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 342336612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro insertInTransaction(streamUri, streamItemValues); 34246802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 34256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } finally { 34266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.close(); 34276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 34286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 3429e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3430e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3431bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3432a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 34335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLastStatusUpdateId(contactId); 3434a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3435a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3436a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 34371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 34381f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3439e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda /** Converts a status update to HTML. */ 3440e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda private String statusUpdateToHtml(String status) { 34414747809486541f7a3d342d3e1dd48fb5ea255ad6Flavio Lerda return TextUtils.htmlEncode(status); 3442e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda } 3443e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda 34440bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann private String getResourceName(Resources resources, String expectedType, Integer resourceId) { 34450bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann try { 34460bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (resourceId == null || resourceId == 0) return null; 34470bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 34480bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann // Resource has an invalid type (e.g. a string as icon)? ignore 34490bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann final String resourceEntryName = resources.getResourceEntryName(resourceId); 34500bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann final String resourceTypeName = resources.getResourceTypeName(resourceId); 34510bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (!expectedType.equals(resourceTypeName)) { 34520bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Log.w(TAG, "Resource " + resourceId + " (" + resourceEntryName + ") is of type " + 34530bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann resourceTypeName + " but " + expectedType + " is required."); 34540bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return null; 34550bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34560bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 34570bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return resourceEntryName; 34580bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } catch (NotFoundException e) { 34590bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return null; 34600bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34610bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34620bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 34634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3464de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 3465bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3466b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 3467b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 34685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 34695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 34705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 3471078f588cef389358adabc579de00747878f3c108Dave Santoro mActiveDb.set(mContactsHelper.getWritableDatabase()); 34725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 34735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 3474b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3475f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3476f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 3477508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 3478508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 347935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 34805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 34815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selection, 34825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 34845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case SYNCSTATE_ID: { 34855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String selectionWithId = 34865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 34875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 34885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selectionWithId, 34895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 349135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 34925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE_ID: { 3493b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3494b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3495b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 34965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getSyncState().delete(mActiveDb.get(), selectionWithId, 34975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 3499b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3500cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 3501cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 3502cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 3503cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3504cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3505d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3506d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3507dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 35086bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 35096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 35109fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 35112e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 35122e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 35132e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 35145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 3515fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 35162e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 35172e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 35185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 3519dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 35202e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 35212e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 35229fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 35239fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 35249fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 35259fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 35269fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 35279fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 3528a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 35299fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 35309fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 35319fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 35329fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 35339fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 35349fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 35359fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 35369fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 353760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 35389fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 35395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = query(mActiveDb.get(), lookupQb, null, selection, args, null, null, 35405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null); 35419fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 35429fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 35439fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 3544dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 35459fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 35469fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 35479fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 35489fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 35499fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 35509fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 35519fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 35529fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 35539fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 35549fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 3555d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 3556d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 35572971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 35585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3559fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 3560e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 35612971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 35622971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 35632971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 3564fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 3565fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 3566fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 35672971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35682971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 35692971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 35702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 35722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 3574d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_ID: 3575d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID: { 35762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 35775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return deleteRawContact(rawContactId, mDbHelper.get().getContactId(rawContactId), 3578fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 3579508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3580508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 35810c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 35820c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 3583f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 3584944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 3585f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 358620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 358720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 358848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 358948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 359048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 3591d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case POSTALS_ID: 3592d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA_ID: { 3593508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3594f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 35954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 35964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 3597ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3598ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3599ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3600f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 36015aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 36022971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 36032971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 36042971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 36052971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 36065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS, new String[]{Groups._ID}, 3607e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 36082971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 36092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 36105aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 36112971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 36122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 36132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 36142971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 361581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3616f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 361781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 36182971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3619508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3620508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3621eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 362243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3623e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3624eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3625eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 36265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 36275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 36280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 36291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 36301f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 36313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 36323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 36333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), selection, selectionArgs); 36343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 36363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 36373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 36383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), 36399b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann StreamItems._ID + "=?", 36403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 36413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 364382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 364482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro mSyncToNetwork |= !callerIsSyncAdapter; 364582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String rawContactId = uri.getPathSegments().get(1); 364682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String streamItemId = uri.getLastPathSegment(); 364782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro return deleteStreamItems(uri, new ContentValues(), 364882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=? AND " + StreamItems._ID + "=?", 364982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{rawContactId, streamItemId}); 365082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 365182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 365282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 36533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 36543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 36555d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro String streamItemId = uri.getPathSegments().get(1); 36565d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro String selectionWithId = 36575d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro (StreamItemPhotos.STREAM_ITEM_ID + "=" + streamItemId + " ") 36585d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 36595d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro return deleteStreamItemPhotos(uri, new ContentValues(), 36605d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro selectionWithId, selectionArgs); 36613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 36633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 36643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 36653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 36663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 36673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItemPhotos(uri, new ContentValues(), 36683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " 36693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + StreamItemPhotos.STREAM_ITEM_ID + "=?", 36703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 36713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 367381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 367481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 36753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 367681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3677508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 36784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36801c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3681ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 36825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long groupMembershipMimetypeId = mDbHelper.get() 368394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 36845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 368594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 368694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 368794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 368894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3689f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 36905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 369194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 369294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 369394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3694f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 36955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, 36965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null); 369794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 369894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 36991a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 370094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 370194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 370294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 37035aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 37045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final int count = mActiveDb.get().delete(Tables.SETTINGS, selection, selectionArgs); 37051a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3706e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3707e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3708e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3709dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int deleteContact(long contactId, boolean callerIsSyncAdapter) { 371096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 37115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 371296b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 371396b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 3714cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3715cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3716cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3717dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 3718cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3719cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3720cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3721cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3722cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 37233826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 37243826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 37255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3726cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3727cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3728fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 37295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().invalidateAggregationExceptionCache(); 37303826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 37313826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 373282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro // Find and delete stream items associated with the raw contact. 373382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, 373482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{StreamItems._ID}, 373582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 373682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro null, null, null); 373782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro try { 373882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro while (c.moveToNext()) { 373982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro deleteStreamItem(c.getLong(0)); 374082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 374182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } finally { 374282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro c.close(); 374382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 374482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 3745d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro if (callerIsSyncAdapter || rawContactIsLocal(rawContactId)) { 37465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.PRESENCE, 37475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 37485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().delete(Tables.RAW_CONTACTS, 37495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro RawContacts._ID + "=" + rawContactId, null); 375041f76a59a31946f6d784dacf9f13d9a4c0bbe203Dave Santoro mAggregator.get().updateAggregateData(mTransactionContext.get(), contactId); 3751fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 375233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 37535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().removeContactIfSingleton(rawContactId); 3754dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 375533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 375633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 375733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3758d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro /** 3759d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro * Returns whether the given raw contact ID is local (i.e. has no account associated with it). 3760d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro */ 3761d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro private boolean rawContactIsLocal(long rawContactId) { 3762d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3763d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro new String[] { 3764d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.ACCOUNT_NAME, 3765d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.ACCOUNT_TYPE, 3766d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.DATA_SET 3767d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro }, 3768d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts._ID + "=?", 3769d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro new String[] {String.valueOf(rawContactId)}, null, null, null); 3770d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro try { 3771d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro return c.moveToFirst() && c.isNull(0) && c.isNull(1) && c.isNull(2); 3772d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } finally { 3773d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro c.close(); 3774d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } 3775d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } 3776d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro 37770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 37789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 37799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 37809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 37819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 37829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 37849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 37855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.PRESENCE, selection, selectionArgs); 37860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 37870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 37883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItems(Uri uri, ContentValues values, String selection, 37893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 37903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream items to be deleted, and check that they belong 37913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // to the account. 37923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 37933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = enforceModifyingAccountForStreamItems( 37943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann account, selection, selectionArgs); 37953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 37973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann for (long streamItemId : streamItemIds) { 37983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(streamItemId); 37993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 38003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 38013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mVisibleTouched = true; 38023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds.size(); 38033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 38043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 38053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItem(long streamItemId) { 38063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 38073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItemPhotos(streamItemId); 38085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEMS, StreamItems._ID + "=?", 38093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 38103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 38113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 38123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(Uri uri, ContentValues values, String selection, 38133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 38143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream item photos to be deleted, and check that they 38153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // belong to the account. 38163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 38173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 38183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 38193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 38205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, selection, selectionArgs); 38213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 38223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 38233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(long streamItemId) { 38243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 38255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, 38265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro StreamItemPhotos.STREAM_ITEM_ID + "=?", 38273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 38283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 38293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 3830dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) { 383181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 383281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3833cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3834cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3835cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3836cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3837cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3838cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3839dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues, callerIsSyncAdapter); 3840cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3841cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 38424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3843de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3844de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3845bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3846b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3847b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3848b5a4add17815167d20a90645779df34cdf45280dFred Quintana 38495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 38505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 3851078f588cef389358adabc579de00747878f3c108Dave Santoro mActiveDb.set(mContactsHelper.getWritableDatabase()); 38525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 38535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 385435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 385500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 385600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3857b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3858b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 38591129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 38605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().syncStateUpdated(rowId, data); 3861b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3862b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3863b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3864f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3865f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 386600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 386735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 38685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 38695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().update(mActiveDb.get(), values, 3870b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3871b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3872b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3873b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3874b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3875b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3876b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 38775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().update(mActiveDb.get(), values, 38785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionWithId, selectionArgs); 38795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 38805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 38815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE_ID: { 38825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection = appendAccountToSelection(uri, selection); 38835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String selectionWithId = 38845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 38855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 38865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getSyncState().update(mActiveDb.get(), values, 3887b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3888b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 388935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3890d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case CONTACTS: 3891d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE: { 3892dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 389300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 389400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 389500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3896d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3897dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter); 3898c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3899c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3900c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 39012e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 39022e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 39032e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 39042e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 39052e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 39065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 3907fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 39082e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 39092e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 39105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 3911dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(contactId, values, callerIsSyncAdapter); 39122e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 39132e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 39142e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 3915d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 3916d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 3917d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 3918d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro final String rawContactId = uri.getPathSegments().get(segment); 39197d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 39207d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 39217d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 39227d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 39237d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 39247d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 39257d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 39267d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 39270c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 39280c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 3929944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3930f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 393181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3932f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 393381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 393420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 393520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3936c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 393748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 393848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 393948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 394048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3941f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 394281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3943f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 394481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 394500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 394600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 39477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case RAW_CONTACTS: 39495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_RAW_CONTACTS: { 39505ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 3951dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, selection, selectionArgs, callerIsSyncAdapter); 39527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 39537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 395633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 39574529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 39584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 39594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 3960dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND(" + selection + ")", selectionArgs, 3961dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 39624529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 39634da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 3964dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1, 3965dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 39664529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 39677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 39687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3970ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 39715aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3972f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 397381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3974f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 397581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3976ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3977ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3978ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3979ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3980ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 39814da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 39824da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 398373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 39845aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 39855aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 398681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3987f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 398881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3989ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3990ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3991ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3992127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 39935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count = updateAggregationException(mActiveDb.get(), values); 3994b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3995b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3996b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3997eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3998e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3999e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 400043880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 4001eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 4002eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 4003eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 40045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 40055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 40069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 40079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 40089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 40113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItems(uri, values, selection, selectionArgs); 40123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 40133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 40169b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann count = updateStreamItems(uri, values, StreamItems._ID + "=?", 40173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 40183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 40193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 402182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 402282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String rawContactId = uri.getPathSegments().get(1); 402382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String streamItemId = uri.getLastPathSegment(); 402482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro count = updateStreamItems(uri, values, 402582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=? AND " + StreamItems._ID + "=?", 402682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{rawContactId, streamItemId}); 402782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro break; 402882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 402982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 40303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 40313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, selection, selectionArgs); 40323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 40333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 40363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 40373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 40383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotos.STREAM_ITEM_ID + "=?", new String[]{streamItemId}); 40393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 40403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 40433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 40443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 40453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 40463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " + 40473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?", 40483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 40493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 40503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 405272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case DIRECTORIES: { 4053bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanPackagesByUid(Binder.getCallingUid()); 405472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov count = 1; 4055d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 4056d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4057d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 405846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa case DATA_USAGE_FEEDBACK_ID: { 405946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (handleDataUsageFeedback(uri)) { 406046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 1; 406146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 406246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 0; 406346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 406446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa break; 406546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 406646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 406781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 406881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 4069f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 407081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 407100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 407200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 407300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 40744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 40754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 40769705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 40779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 40789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 40799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 40809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 40819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 40829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 40835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro updateCount = mActiveDb.get().update(Tables.STATUS_UPDATES, 40849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 40859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 40869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 40879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 40909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 40919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 40925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro updateCount = mActiveDb.get().update(Tables.PRESENCE, settableValues, 40939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 40949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 40969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 40979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 40989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItems(Uri uri, ContentValues values, String selection, 41013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 41023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream items can't be moved to a new raw contact. 41033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItems.RAW_CONTACT_ID); 41043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 41053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream items being updated belong to the account. 41063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 41073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItems(account, selection, selectionArgs); 41083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 41096802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to update accounts params - they don't exist in the stream items table. 41106802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_NAME); 41116802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_TYPE); 41126802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 41133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If there's been no exception, the update should be fine. 41145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.STREAM_ITEMS, values, selection, selectionArgs); 41153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 41163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 41173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItemPhotos(Uri uri, ContentValues values, String selection, 41183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 41193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream item photos can't be moved to a new stream item. 41203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItemPhotos.STREAM_ITEM_ID); 41213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 41223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream item photos being updated belong to the account. 41233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 41243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 41253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 41266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to update accounts params - they don't exist in the stream item 41276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // photos table. 41286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_NAME); 41296802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_TYPE); 41306802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 41316802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo (since we're updating, it's valid for the photo to not be present). 41326802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (processStreamItemPhoto(values, true)) { 41336802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // If there's been no exception, the update should be fine. 41345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.STREAM_ITEM_PHOTOS, values, selection, 41355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 41366802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 41376802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return 0; 41383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 41393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 41409705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 41419705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 41429705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 41439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 41449705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 41459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 41469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 41479705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 41489705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 41499705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 41509705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41519705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 41529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 41539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 41549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 41559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 41569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 41579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 41589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 41599705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 41609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 41619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 41629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 41639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 41649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 41659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 41679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 41689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 41699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 4170aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.CHAT_CAPABILITY, values, 4171aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori StatusUpdates.CHAT_CAPABILITY); 41729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 41739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 41749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41755aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 4176f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 417773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4178ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 4179ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 418073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 4181f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 418273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 418373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 418473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 418573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 418673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 418773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 418873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 418973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 41905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().update(Tables.GROUPS, updatedValues, selectionWithId, 41915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 41921a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 41931a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 419494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 419543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 419643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO: This will not work for groups that have a data set specified, since the content 419743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // resolver will not be able to request a sync for the right source (unless it is updated 419843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // to key off account with data set). 41996ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 42001129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 42015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 4202e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 42036ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 42046ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 42056ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 42066ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 42076ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 42086ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 42096ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 421024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 42116ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 4212ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 42136ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 42146ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 42156ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 42166ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 42176ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 42186ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 42196ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 42206ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 422194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 422294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 422394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 4224b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 4225b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 42265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final int count = mActiveDb.get().update(Tables.SETTINGS, values, selection, selectionArgs); 42271a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 42281a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 4229e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4230e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 4231e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4232e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4233dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs, 4234dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 42354529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 42364529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 42374529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 42384529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 423973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 424097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 424197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 424297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0"); 424397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 424497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 42454529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 42465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS, 424751bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 42484529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 42494529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 42504529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 42514529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 4252dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContact(rawContactId, values, callerIsSyncAdapter); 42534529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 42544529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 42554529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 42564529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 42574529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 42584529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 42594529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 42604529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 42614529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 4262dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContact(long rawContactId, ContentValues values, 4263dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 426496b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 426596b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 426619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 426719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 426819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 4269ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 4270ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 427143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet = null; 427219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 42735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 42745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, mSelectionArgs1, null, null, null); 427519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 427619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 427719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 4278ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 4279ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 428043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro dataSet = cursor.getString(RawContactsQuery.DATA_SET); 428119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 428219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 428319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 428419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 428519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 428619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 428719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 4288f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 42895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 42905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 4291f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 4292f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 4293f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 4294f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 4295f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 4296f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 42975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId, aggregationMode, false); 4298f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 4299f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 4300433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 4301dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 4302dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4303dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana values.getAsLong(RawContacts.STARRED) != 0); 4304dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 43055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateStarred(rawContactId); 4306dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 4307dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then update the 4308dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // favorites group membership based on whether or not this contact is starred. 4309dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // If it is starred, add a group membership, if one doesn't already exist 4310dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // otherwise delete any matching group memberships. 4311dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 43125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro boolean starred = 0 != DatabaseUtils.longForQuery(mActiveDb.get(), 4313dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SELECTION_STARRED_FROM_RAW_CONTACTS, 4314dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}); 4315dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred); 4316dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4317dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4318dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 4319dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then add a 4320dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // group membership to the group marked as AutoAdd, if any. 4321dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 4322dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 4323433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 4324dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 4325285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 43265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLookupKeyForRawContact(mActiveDb.get(), rawContactId); 4327285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 4328f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 4329f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 4330f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 4331f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 4332f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 43335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().resetNameVerifiedForOtherRawContacts(rawContactId); 4334f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 43355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateDisplayNameForRawContact(mActiveDb.get(), rawContactId); 4336f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 433719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 43385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactInserted(rawContactId, 433943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new AccountWithDataSet(accountName, accountType, dataSet)); 434019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 43415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 434333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 434433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 4345321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 4346f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 434720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 434820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 434920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 43505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 435120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 435220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 435320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 435420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 435520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 43565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 435720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 435820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 435997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 436097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 436197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov Data.IS_READ_ONLY + "=0"); 436297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 436397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 4364653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 436520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4366653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 4367653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 43685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryLocal(uri, 4369f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro DataRowHandler.DataUpdateQuery.COLUMNS, 43705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, selectionArgs, null, -1 /* directory ID */); 4371653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 4372653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 4373f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 437420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 4375653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 4376653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 437720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 437820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4379653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 438020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 438120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4382f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 4383653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 4384653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 4385321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4386653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 4387f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String mimeType = c.getString(DataRowHandler.DataUpdateQuery.MIMETYPE); 4388a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 4389f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro boolean updated = 43905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro rowHandler.update(mActiveDb.get(), mTransactionContext.get(), values, c, 43915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro callerIsSyncAdapter); 4392f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) { 4393f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 4394a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 4395f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return updated ? 1 : 0; 4396321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4397321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 43988c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 4399dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 44008c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 44015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.CONTACTS, 44025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[] { Contacts._ID }, selection, selectionArgs, null, null, null); 44038c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 44048c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 44058c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 440624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 4407dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateContactOptions(contactId, values, callerIsSyncAdapter); 44088c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 44098c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 44108c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 44118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 44128c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 44138c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 44148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 44158c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 44168c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4417dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateContactOptions(long contactId, ContentValues values, 4418dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 4419d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 44208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4421b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 4422d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4423b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 4424d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4425b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 4426d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4427b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 4428d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4429b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 4430d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 4431d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4432d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 44338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 4434d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 4435d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 4436d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 44378c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 4438c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 44398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 4440c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 4441c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 44424da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 44435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?" 444497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov + " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1); 44458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4446dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) { 44475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS, 4448dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?", 4449dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null, null, null); 4450dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 4451dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (cursor.moveToNext()) { 4452dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long rawContactId = cursor.getLong(0); 4453dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4454dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.getAsLong(RawContacts.STARRED) != 0); 4455dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4456dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 4457dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana cursor.close(); 4458dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4459dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4460dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 44618c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 44628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 44638c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4464b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 44658c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4466b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 44678c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4468b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 44698c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4470b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 44718c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4472b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 44738c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 44748c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 44755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int rslt = mActiveDb.get().update(Tables.CONTACTS, mValues, Contacts._ID + "=?", 44765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mSelectionArgs1); 44776e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 44789b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 44799b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 44805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 44815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 44829b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 44839b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 4484f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 4485d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4486127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 4487127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 44880c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 44890c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 449080c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 4491ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId1; 4492ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId2; 44930c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 44940c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 44950c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 44960c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 44970c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 44980c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 4499b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4500127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 45010c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 45024da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 45034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 45040c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 45054da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 45064da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 45070c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 45086bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 45096bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 45100c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 45110c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 45120c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 45130c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 4514127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 4515127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 45165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().invalidateAggregationExceptionCache(); 45175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId1, 451869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 45195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId2, 452069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 4521dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 45225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateContact(mTransactionContext.get(), db, rawContactId1); 45235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateContact(mTransactionContext.get(), db, rawContactId2); 4524127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 4525127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 4526127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 4527127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 4528b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4529b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 453070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 4531bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 45323826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 45333826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 4534bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected boolean updateAccountsInBackground(Account[] accounts) { 4535f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 4536e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov boolean accountsChanged = false; 45375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); 45385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 45395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.beginTransaction(); 45405dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro 45415dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro // WARNING: This method can be run in either contacts mode or profile mode. It is 45425dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro // absolutely imperative that no calls be made inside the following try block that can 45435dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro // interact with the contacts DB. Otherwise it is quite possible for a deadlock to occur. 454470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 454543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> existingAccountsWithDataSets = 454643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro findValidAccountsWithDataSets(Tables.ACCOUNTS); 4547743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 454843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add a row to the ACCOUNTS table (with no data set) for each new account. 4549743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 455043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = new AccountWithDataSet( 455143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro account.name, account.type, null); 455243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!existingAccountsWithDataSets.contains(accountWithDataSet)) { 4553e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 455443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 455543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add an account entry with an empty data set to match the account. 45565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 455743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ", " + RawContacts.ACCOUNT_TYPE + ", " + RawContacts.DATA_SET 455843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ") VALUES (?, ?, ?)", 455943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new String[] { 456043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 456143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 456243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 456343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }); 4564743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 4565743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 456648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 456743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Check each of the existing sub-accounts against the account list. If the owning 456843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // account no longer exists, the sub-account and all its data should be deleted. 456943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro List<AccountWithDataSet> accountsWithDataSetsToDelete = 457043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new ArrayList<AccountWithDataSet>(); 457143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro List<Account> accountList = Arrays.asList(accounts); 457243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : existingAccountsWithDataSets) { 457343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Account owningAccount = new Account( 457443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), accountWithDataSet.getAccountType()); 457543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!accountList.contains(owningAccount)) { 457643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsWithDataSetsToDelete.add(accountWithDataSet); 457743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 457870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 457970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 458043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!accountsWithDataSetsToDelete.isEmpty()) { 4581e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 458243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : accountsWithDataSetsToDelete) { 458343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Log.d(TAG, "removing data for removed account " + accountWithDataSet); 458443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String[] accountParams = new String[] { 458543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 458643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType() 458743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }; 458843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String[] accountWithDataSetParams = accountWithDataSet.getDataSet() == null 458943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ? accountParams 459043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro : new String[] { 459143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 459243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 459343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 459443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }; 459543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String groupsDataSetClause = " AND " + Groups.DATA_SET 459643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 459743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String rawContactsDataSetClause = " AND " + RawContacts.DATA_SET 459843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 4599f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String settingsDataSetClause = " AND " + Settings.DATA_SET 4600f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 460143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 46025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4603e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 4604e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 460543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Groups.ACCOUNT_TYPE + " = ?" + 460643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro groupsDataSetClause, accountWithDataSetParams); 46075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4608e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 4609e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 4610e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "SELECT " + RawContacts._ID + 4611e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4612e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 461343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 461443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause + ")", accountWithDataSetParams); 46155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4616c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "DELETE FROM " + Tables.STREAM_ITEM_PHOTOS + 4617c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItemPhotos.STREAM_ITEM_ID + " IN (" + 4618c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + StreamItems._ID + 4619c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.STREAM_ITEMS + 4620c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItems.RAW_CONTACT_ID + " IN (" + 4621c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + RawContacts._ID + 4622c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.RAW_CONTACTS + 4623c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4624c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 4625c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro rawContactsDataSetClause + "))", 4626c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro accountWithDataSetParams); 4627c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro db.execSQL( 4628c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "DELETE FROM " + Tables.STREAM_ITEMS + 4629c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItems.RAW_CONTACT_ID + " IN (" + 4630c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + RawContacts._ID + 4631c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.RAW_CONTACTS + 4632c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4633c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 4634c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro rawContactsDataSetClause + ")", 4635c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro accountWithDataSetParams); 4636c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro db.execSQL( 4637e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 4638e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 463943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 464043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause, accountWithDataSetParams); 46415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4642e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 4643e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 4644f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro " AND " + Settings.ACCOUNT_TYPE + " = ?" + 4645f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsDataSetClause, accountWithDataSetParams); 46465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4647e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 4648e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 464943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + "=?" + 465043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause, accountWithDataSetParams); 46515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4652d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov "DELETE FROM " + Tables.DIRECTORIES + 4653d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " WHERE " + Directory.ACCOUNT_NAME + "=?" + 465443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Directory.ACCOUNT_TYPE + "=?", accountParams); 46554458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov resetDirectoryCache(); 4656e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 4657e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 465833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 465933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 4660e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov // names or photos. If so, fix up those contacts. 466133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 46625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = db.rawQuery("SELECT " + Contacts._ID + 466333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 466433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 466569cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 466669cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 466769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 466833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 466933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 467069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 467169cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 467233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 467333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 467433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 467533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 467633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 467733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 467833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 467933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 468033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 46815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateAggregateData(mTransactionContext.get(), contactId); 468233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 46835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateAllVisible(); 46845dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro 46855dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro // Don't bother updating the search index if we're in profile mode - there is no 46865dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro // search index for the profile DB, and updating it for the contacts DB in this case 46875dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro // makes no sense and risks a deadlock. 46885dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro if (!inProfileMode()) { 46895dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro updateSearchIndexInTransaction(); 46905dccfb059f5df0e9fdba026bcfbed677f44922cdDave Santoro } 469133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 469233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 469343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Now that we've done the account-based additions and subtractions from the Accounts 469443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // table, check for raw contacts that have been added with a data set and add Accounts 469543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // entries for those if necessary. 469643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro existingAccountsWithDataSets = findValidAccountsWithDataSets(Tables.ACCOUNTS); 469743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> rawContactAccountsWithDataSets = 469843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro findValidAccountsWithDataSets(Tables.RAW_CONTACTS); 469943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactAccountsWithDataSets.removeAll(existingAccountsWithDataSets); 470043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 470143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Any remaining raw contact sub-accounts need to be added to the Accounts table. 470243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : rawContactAccountsWithDataSets) { 470343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsChanged = true; 470443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 470543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add an account entry to match the raw contact. 47065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 470743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ", " + RawContacts.ACCOUNT_TYPE + ", " + RawContacts.DATA_SET 470843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ") VALUES (?, ?, ?)", 470943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new String[] { 471043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 471143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 471243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 471343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }); 471443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 471543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 4716e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (accountsChanged) { 471743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO: Should sync state take data set into consideration? 47185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getSyncState().onAccountsChanged(db, accounts); 4719e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 47205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.setTransactionSuccessful(); 472170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 47225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.endTransaction(); 472370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 472473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 47253826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 47263826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (accountsChanged) { 47273826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateContactsAccountCount(accounts); 47283826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 47293826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 47303826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 4731afb84050536a4472c13efc0e996d31132d254605Dmitri Plotnikov return accountsChanged; 473270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4733619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 47343826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateContactsAccountCount(Account[] accounts) { 47353826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov int count = 0; 47363826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov for (Account account : accounts) { 47373826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (isContactsAccount(account)) { 47383826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov count++; 47393826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 47403826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 47413826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mContactsAccountCount = count; 47423826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 47433826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 47443826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov protected boolean isContactsAccount(Account account) { 47453826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov final IContentService cs = ContentResolver.getContentService(); 47463826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov try { 47473826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return cs.getIsSyncable(account, ContactsContract.AUTHORITY) > 0; 47483826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } catch (RemoteException e) { 47493826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov Log.e(TAG, "Cannot obtain sync flag for account: " + account, e); 47503826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return false; 47513826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 47523826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 47533826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 475472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPackageChanged(String packageName) { 4755bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_DIRECTORIES, packageName); 4756d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4757d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4758619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 475943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Finds all distinct account types and data sets present in the specified table. 4760627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 476143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private Set<AccountWithDataSet> findValidAccountsWithDataSets(String table) { 476243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> accountsWithDataSets = new HashSet<AccountWithDataSet>(); 47635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().rawQuery( 476443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro "SELECT DISTINCT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 476543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro "," + RawContacts.DATA_SET + 476643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " FROM " + table, null); 4767627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4768627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 476991abbc9f691297594262d1f2d79acb744a66712cDave Santoro if (!c.isNull(0) && !c.isNull(1)) { 477043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsWithDataSets.add( 477143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new AccountWithDataSet(c.getString(0), c.getString(1), c.getString(2))); 4772627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4773627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4774627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 4775627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 4776627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 477743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro return accountsWithDataSets; 4778627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4779627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 47804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 47814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 47824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 478315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 478415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mReadAccessLatch); 478515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 478636612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro // Enforce stream items access check if applicable. 478736612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro enforceSocialStreamReadPermission(uri); 478836612112760df799ef89f7e324e5dfabd5ca0d2bDave Santoro 47895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Query the profile DB if appropriate. 47905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 47915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 47925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileProvider.query(uri, projection, selection, selectionArgs, sortOrder); 47935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 47945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 47955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Otherwise proceed with a normal query against the contacts DB. 47965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 47975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mContactsHelper.getReadableDatabase()); 4798d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY); 4799385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directory == null) { 4800b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 48015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1)); 4802385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directory.equals("0")) { 4803b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 48043716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 48055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Directory.DEFAULT)); 4806d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } else if (directory.equals("1")) { 4807b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 48083716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 48095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Directory.LOCAL_INVISIBLE)); 4810d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4811d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4812d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryInfo directoryInfo = getDirectoryAuthority(directory); 4813d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo == null) { 4814a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov Log.e(TAG, "Invalid directory ID: " + uri); 4815a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov return null; 4816d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4817d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4818d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Builder builder = new Uri.Builder(); 4819d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.scheme(ContentResolver.SCHEME_CONTENT); 4820d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.authority(directoryInfo.authority); 4821d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.encodedPath(uri.getEncodedPath()); 4822d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountName != null) { 4823d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, directoryInfo.accountName); 4824d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4825d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountType != null) { 4826d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, directoryInfo.accountType); 4827d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 48282e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 48292e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limit = getLimit(uri); 48302e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov if (limit != null) { 48312e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov builder.appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, limit); 48322e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov } 48332e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 4834d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Uri directoryUri = builder.build(); 483509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 483609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (projection == null) { 483709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov projection = getDefaultProjection(uri); 483809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 483909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 4840332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov Cursor cursor = getContext().getContentResolver().query(directoryUri, projection, selection, 4841d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs, sortOrder); 48426ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 48436ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (cursor == null) { 48446ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 48456ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48466ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 4847547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro CrossProcessCursor crossProcessCursor = getCrossProcessCursor(cursor); 4848547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (crossProcessCursor != null) { 4849b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, cursor); 4850547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } else { 4851b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return matrixCursorFromCursor(addSnippetExtrasToCursor(uri, cursor)); 4852547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 48533716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 48543716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 4855b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private Cursor addSnippetExtrasToCursor(Uri uri, Cursor cursor) { 4856547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 4857547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro // If the cursor doesn't contain a snippet column, don't bother wrapping it. 4858547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (cursor.getColumnIndex(SearchSnippetColumns.SNIPPET) < 0) { 4859b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 4860547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 4861547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 48623716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Parse out snippet arguments for use when snippets are retrieved from the cursor. 48633716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String[] args = null; 48643716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String snippetArgs = 48653716f1447ceb21180d1301790eabd8b9453f486dDave Santoro getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 48663716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (snippetArgs != null) { 48673716f1447ceb21180d1301790eabd8b9453f486dDave Santoro args = snippetArgs.split(","); 48683716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 48693716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 48703716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String query = uri.getLastPathSegment(); 48713716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String startMatch = args != null && args.length > 0 ? args[0] 48723716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_START_MATCH; 48733716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String endMatch = args != null && args.length > 1 ? args[1] 48743716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_END_MATCH; 48753716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String ellipsis = args != null && args.length > 2 ? args[2] 48763716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_ELLIPSIS; 48773716f1447ceb21180d1301790eabd8b9453f486dDave Santoro int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 48783716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 48793716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 4880b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Snippet data is needed for the snippeting on the client side, so store it in the cursor 4881b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (cursor instanceof AbstractCursor && deferredSnippetingRequested(uri)){ 4882b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle oldExtras = cursor.getExtras(); 4883b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle extras = new Bundle(); 4884b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (oldExtras != null) { 4885b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putAll(oldExtras); 4886b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4887b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putString(ContactsContract.DEFERRED_SNIPPETING_QUERY, query); 4888b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 4889b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson ((AbstractCursor) cursor).setExtras(extras); 48905517770250b3afa4fd88b6869c3244680821d222Dave Santoro } 4891b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 4892b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4893b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 4894b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private Cursor addDeferredSnippetingExtra(Cursor cursor) { 4895b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (cursor instanceof AbstractCursor){ 4896b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle oldExtras = cursor.getExtras(); 4897b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle extras = new Bundle(); 4898b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (oldExtras != null) { 4899b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putAll(oldExtras); 4900b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4901b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putBoolean(ContactsContract.DEFERRED_SNIPPETING, true); 4902b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson ((AbstractCursor) cursor).setExtras(extras); 4903b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4904b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 49056ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 49066ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 49076ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov private CrossProcessCursor getCrossProcessCursor(Cursor cursor) { 49086ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov Cursor c = cursor; 49096ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (c instanceof CrossProcessCursor) { 49106ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return (CrossProcessCursor) c; 49116ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else if (c instanceof CursorWindow) { 49126ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return getCrossProcessCursor(((CursorWrapper) c).getWrappedCursor()); 49136ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else { 49146ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 49156ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 49166ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 49176ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 49186ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public MatrixCursor matrixCursorFromCursor(Cursor cursor) { 49196ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 49206ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov int numColumns = cursor.getColumnCount(); 49216ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov String data[] = new String[numColumns]; 49226ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov cursor.moveToPosition(-1); 49236ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov while (cursor.moveToNext()) { 49246ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov for (int i = 0; i < numColumns; i++) { 49256ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov data[i] = cursor.getString(i); 49266ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 49276ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov newCursor.addRow(data); 4928332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov } 49296ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return newCursor; 4930d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4931d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4932d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final class DirectoryQuery { 4933d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 4934d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory._ID, 4935d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.DIRECTORY_AUTHORITY, 4936d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_NAME, 4937d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_TYPE 4938d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov }; 4939d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4940d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int DIRECTORY_ID = 0; 4941d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int AUTHORITY = 1; 4942d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_NAME = 2; 4943d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_TYPE = 3; 4944d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4945d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4946d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 4947d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Reads and caches directory information for the database. 4948d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 4949d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private DirectoryInfo getDirectoryAuthority(String directoryId) { 49504458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized (mDirectoryCache) { 49514458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (!mDirectoryCacheValid) { 49524458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.clear(); 49535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getReadableDatabase(); 495449d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Cursor cursor = db.query(Tables.DIRECTORIES, 49554458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryQuery.COLUMNS, 49564458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov null, null, null, null, null); 49574458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov try { 49584458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov while (cursor.moveToNext()) { 49594458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryInfo info = new DirectoryInfo(); 49604458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov String id = cursor.getString(DirectoryQuery.DIRECTORY_ID); 49614458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.authority = cursor.getString(DirectoryQuery.AUTHORITY); 49624458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME); 49634458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE); 49644458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.put(id, info); 49654458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 49664458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } finally { 49674458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov cursor.close(); 4968d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 49694458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = true; 4970d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4971d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 49724458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov return mDirectoryCache.get(directoryId); 49734458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 4974d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4975d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 497672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void resetDirectoryCache() { 49774458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized(mDirectoryCache) { 49784458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = false; 49794458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 498072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 498172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 498223ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki private boolean hasColumn(String[] projection, String column) { 498323ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki if (projection == null) { 498423ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki return true; // Null projection means "all columns". 498523ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki } 498623ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki 498723ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki for (int i = 0; i < projection.length; i++) { 498823ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki if (column.equalsIgnoreCase(projection[i])) return true; 498923ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki } 499023ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki return false; 499123ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki } 499223ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki 49935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro protected Cursor queryLocal(Uri uri, String[] projection, String selection, 49945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String[] selectionArgs, String sortOrder, long directoryId) { 4995bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 4996bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 4997bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 49980b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 49995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 50005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 5001078f588cef389358adabc579de00747878f3c108Dave Santoro mActiveDb.set(mContactsHelper.getReadableDatabase()); 50025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 500335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 5004d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 50051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 5006c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 5007b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean snippetDeferred = false; 5008c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 50092ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // The expression used in bundleLetterCountExtras() to get count. 50102ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki String addressBookIndexerCountExpression = null; 50112ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 5012a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 50134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 501435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 50155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 50165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().query(mActiveDb.get(), projection, selection, 50175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs, sortOrder); 501835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 5019d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 5020763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 50214b64b6e8f448938434cb1e022a4e7dfaae8f9c8cMakoto Onuki appendLocalDirectorySelectionIfNeeded(qb, directoryId); 5022619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 5023619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5024619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 5025d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 50264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 5027763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 50284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 50294da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 50306bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 50316bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 50326bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 50335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 50345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 50355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 50365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 50375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 50385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 5039fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 50405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 5041a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 50425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 50435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 50445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 50455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 5046763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 5047a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 50485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 5049a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 5050a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 5051a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 50525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 50535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 5056763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 50574da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 50585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey))); 50594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 50605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 50615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50632149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_DATA: 5064bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_DATA: 5065bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_PHOTO: 5066bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_PHOTO: { 50672149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 50682149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov int segmentCount = pathSegments.size(); 50692149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount < 4) { 50705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 50712149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov "Missing a lookup key", uri)); 50722149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50732149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String lookupKey = pathSegments.get(2); 50742149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount == 5) { 50752149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 50762149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 50772149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(lookupQb, uri, projection, false); 5078bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (match == CONTACTS_LOOKUP_PHOTO || match == CONTACTS_LOOKUP_ID_PHOTO) { 5079bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 5080bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 5081a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 50825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 5083a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 5084a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey); 5085a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 50862149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov return c; 50872149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50882149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50892149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov // TODO see if the contact exists but has no data rows (rare) 50902149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50912149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50922149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 50935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 50942149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 509524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 5096bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (match == CONTACTS_LOOKUP_PHOTO || match == CONTACTS_LOOKUP_ID_PHOTO) { 5097bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 5098bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 50992149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov qb.appendWhere(" AND " + Data.CONTACT_ID + "=?"); 51002149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov break; 51012149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 51022149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 51033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_ID_STREAM_ITEMS: { 51043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(uri.getPathSegments().get(1)); 51053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 51063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 5107af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann qb.appendWhere(StreamItems.CONTACT_ID + "=?"); 51083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 51093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 51103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 51113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_STREAM_ITEMS: 51123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_ID_STREAM_ITEMS: { 51133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<String> pathSegments = uri.getPathSegments(); 51143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int segmentCount = pathSegments.size(); 51153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount < 4) { 51165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 51173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann "Missing a lookup key", uri)); 51183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 51193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String lookupKey = pathSegments.get(2); 51203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount == 5) { 51213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(pathSegments.get(3)); 51223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 51233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(lookupQb); 51245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 51253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann projection, selection, selectionArgs, sortOrder, groupBy, limit, 5126af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann StreamItems.CONTACT_ID, contactId, 5127af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann StreamItems.CONTACT_LOOKUP_KEY, lookupKey); 51283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c != null) { 51293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return c; 51303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 51313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 51323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 51333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 51345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 51353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 51363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(RawContacts.CONTACT_ID + "=?"); 51373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 51383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 51393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 5140f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 514142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 51425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 5143ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 5144f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 51454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 514624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 51474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 5148f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 5149f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 5150f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 515142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 515242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 515342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 51545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().rawQuery( 515542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 515642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 515742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 515842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 515942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 516042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 5161ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 5162916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 5163b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean deferredSnipRequested = deferredSnippetingRequested(uri); 5164ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 5165916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 5166ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 51677ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet( 5168b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson qb, uri, projection, filterParam, directoryId, 5169b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnipRequested); 5170b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson snippetDeferred = isSingleWordQuery(filterParam) && 5171b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnipRequested && snippetNeeded(projection); 5172ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5173ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5174ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 5175ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 5176ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 51772f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Basically the resultant SQL should look like this: 51782f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing starred items) 51792f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 51802f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing frequently contacted items) 51812f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // ORDER BY ... 51822f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 51832f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final boolean phoneOnly = readBooleanQueryParameter( 51842f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa uri, ContactsContract.STREQUENT_PHONE_ONLY, false); 51852f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (match == CONTACTS_STREQUENT_FILTER && uri.getPathSegments().size() > 3) { 51864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 51874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5188e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 51895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 51902f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa selection = DbQueryUtils.concatenateClauses(selection, sb.toString()); 51914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 51924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 51932f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] subProjection = null; 51945e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 51952f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa subProjection = appendProjectionArg(projection, TIMES_USED_SORT_COLUMN); 51965e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 51975e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 51984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 51994928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false); 52004928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(phoneOnly ? 52014928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa sStrequentPhoneOnlyStarredProjectionMap 52024928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa : sStrequentStarredProjectionMap); 52039dbfd650ccf93714f3266e80f9fbdbcb526ae7b3Daisuke Miyakawa if (phoneOnly) { 52045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(DbQueryUtils.concatenateClauses( 52055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, Contacts.HAS_PHONE_NUMBER + "=1")); 52069dbfd650ccf93714f3266e80f9fbdbcb526ae7b3Daisuke Miyakawa } 52072f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 52082f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String starredQuery = qb.buildQuery(subProjection, 520924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Contacts.STARRED + "=1", Contacts._ID, null, null, null); 5210d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 52112f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Reset the builder. 5212d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 52132f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 52144928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 52154928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // Build the second query for frequent part. 52164928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa final String frequentQuery; 52174928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa if (phoneOnly) { 52184928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa final StringBuilder tableBuilder = new StringBuilder(); 52194928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // In phone only mode, we need to look at view_data instead of 52204928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // contacts/raw_contacts to obtain actual phone numbers. One problem is that 52214928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // view_data is much larger than view_contacts, so our query might become much 52224928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // slower. 52234928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // 52244928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // To avoid the possible slow down, we start from data usage table and join 52254928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // view_data to the table, assuming data usage table is quite smaller than 52264928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // data rows (almost always it should be), and we don't want any phone 52274928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // numbers not used by the user. This way sqlite is able to drop a number of 52284928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // rows in view_data in the early stage of data lookup. 52294928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa tableBuilder.append(Tables.DATA_USAGE_STAT 52304928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + " INNER JOIN " + Views.DATA + " " + Tables.DATA 52314928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" 52324928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataColumns.CONCRETE_ID + " AND " 52334928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" 52344928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT_CALL + ")"); 52354928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa appendContactPresenceJoin(tableBuilder, projection, RawContacts.CONTACT_ID); 52364928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa appendContactStatusUpdateJoin(tableBuilder, projection, 52374928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa ContactsColumns.LAST_STATUS_UPDATE_ID); 52384928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 52394928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setTables(tableBuilder.toString()); 52404928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(sStrequentPhoneOnlyFrequentProjectionMap); 52414928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 52424928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa selection, 52434928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa Contacts.STARRED + "=0 OR " + Contacts.STARRED + " IS NULL", 52444928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa MimetypesColumns.MIMETYPE + " IN (" 52454928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + "'" + Phone.CONTENT_ITEM_TYPE + "', " 52464928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + "'" + SipAddress.CONTENT_ITEM_TYPE + "')")); 52474928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa frequentQuery = qb.buildQuery(subProjection, null, null, null, null, null); 52484928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa } else { 52494928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, true); 52504928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(sStrequentFrequentProjectionMap); 52514928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 52524928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa selection, 52535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "(" + Contacts.STARRED + " =0 OR " + Contacts.STARRED + " IS NULL)")); 52544928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa frequentQuery = qb.buildQuery(subProjection, 52554928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa null, Contacts._ID, null, null, null); 52564928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa } 5257d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 5258d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 52592f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String unionQuery = 52602f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 52612f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa STREQUENT_ORDER_BY, STREQUENT_LIMIT); 52622f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 52632f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Here, we need to use selection / selectionArgs (supplied from users) "twice", 52642f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // as we want them both for starred items and for frequently contacted items. 52652f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // 52662f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // e.g. if the user specify selection = "starred =?" and selectionArgs = "0", 52672f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // the resultant SQL should be like: 52682f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 52692f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 52702f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 52712f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] doubledSelectionArgs = null; 52722f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (selectionArgs != null) { 52732f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final int length = selectionArgs.length; 52742f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa doubledSelectionArgs = new String[length * 2]; 52757d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, 0, length); 52767d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, length, length); 52772f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 52782f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 52795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().rawQuery(unionQuery, doubledSelectionArgs); 52802f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (cursor != null) { 52812f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa cursor.setNotificationUri(getContext().getContentResolver(), 5282d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 5283d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 52842f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa return cursor; 5285d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 5286d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 528745ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa case CONTACTS_FREQUENT: { 528845ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, true); 528945ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa qb.setProjectionMap(sStrequentFrequentProjectionMap); 529045ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa groupBy = Contacts._ID; 529145ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa if (!TextUtils.isEmpty(sortOrder)) { 529245ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa sortOrder = FREQUENT_ORDER_BY + ", " + sortOrder; 529345ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } else { 529445ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa sortOrder = FREQUENT_ORDER_BY; 529545ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } 529645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa break; 529745ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } 529845ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa 5299ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 5300763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 5301b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 530271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 53037cf50494501938f175d288077145acf49da8f171Daniel Lehmann String groupMimeTypeId = String.valueOf( 53047cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 53054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 53067cf50494501938f175d288077145acf49da8f171Daniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, groupMimeTypeId); 5307b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5308b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 5309b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5310b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 531124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 531224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 531324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 531424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 531524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 531624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: { 531724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForEntities(qb, uri, projection); 531824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 531924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 532024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 532124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: { 5322ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 532324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.setProjectionMap(sContactsVCardProjectionMap); 532424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 532524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 532624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 5327a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_DATA: { 53284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 532982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 53304da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 53314da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 53326bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 53336bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 533400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 5335a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 53363653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 533782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 53384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 53394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 53403653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 53413653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 53423653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 53433653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 5344a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_ENTITIES: { 5345a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 5346a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 5347a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 5348a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 5349a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 5350a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5351a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5352a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ENTITIES: 5353a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ID_ENTITIES: { 5354a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 5355a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov int segmentCount = pathSegments.size(); 5356a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount < 4) { 53575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 5358a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov "Missing a lookup key", uri)); 5359a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5360a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lookupKey = pathSegments.get(2); 5361a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount == 5) { 5362a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 5363a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 5364a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(lookupQb, uri, projection); 5365a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 5366a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 53675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 5368a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 5369a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.CONTACT_ID, contactId, 5370a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.LOOKUP_KEY, lookupKey); 5371a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 5372a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 5373a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5374a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5375a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5376a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 5377a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 53785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey))); 5379a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?"); 5380a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 5381a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5382a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 53833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 53843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 53853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 53893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 53903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 53919b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann qb.appendWhere(StreamItems._ID + "=?"); 53923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_LIMIT: { 53966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro MatrixCursor cursor = new MatrixCursor(new String[]{StreamItems.MAX_ITEMS}, 1); 53976802030a777c0c3ba1dc029c534cca4784260632Dave Santoro cursor.addRow(new Object[]{MAX_STREAM_ITEMS_PER_RAW_CONTACT}); 53983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return cursor; 53993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 54003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 54013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 54023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 54033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 54043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 54053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 54063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 54073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 54083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 54093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 54103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?"); 54113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 54123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 54133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 54143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 54153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 54163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 54173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 54183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemPhotoId); 54193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 54203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=? AND " + 54213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=?"); 54223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 54233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 54243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 5425f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case PHOTO_DIMENSIONS: { 5426f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro MatrixCursor cursor = new MatrixCursor( 5427f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{DisplayPhoto.DISPLAY_MAX_DIM, DisplayPhoto.THUMBNAIL_MAX_DIM}, 5428f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1); 5429f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro cursor.addRow(new Object[]{mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim}); 5430f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return cursor; 5431f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 5432f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 54334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 543482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54357cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + "=" + 54367cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeIdForPhone()); 54372ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 54388ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa final boolean removeDuplicates = readBooleanQueryParameter( 54398ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa uri, ContactsContract.REMOVE_DUPLICATE_ENTRIES, false); 54408ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa if (removeDuplicates) { 54418ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa groupBy = RawContacts.CONTACT_ID + ", " + Data.DATA1; 54428ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa 54438ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa // In this case, because we dedupe phone numbers, the address book indexer needs 54448ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa // to take it into account too. (Otherwise headers will appear in wrong 54458ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa // positions.) 54468ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa // So use count(distinct pair(CONTACT_ID, PHONE NUMBER)) instead of count(*). 54478ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa // But because there's no such thing as pair() on sqlite, we use 54488ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa // CONTACT_ID || ',' || PHONE NUMBER instead. 54498ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa // This only slows down the query by 14% with 10,000 contacts. 54508ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa addressBookIndexerCountExpression = "DISTINCT " 54518ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa + RawContacts.CONTACT_ID + "||','||" + Data.DATA1; 54528ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa } 54532815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 54542815f58f72f109790585931f601a63ddc02536a5Evan Millar } 54552815f58f72f109790585931f601a63ddc02536a5Evan Millar 545648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 545782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 54597cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54607cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForPhone()); 54614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 546248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 546348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 546448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 5465ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 546646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 546746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 546846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 546946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_CALL; 547046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 547146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 54727cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54737cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForPhone()); 5474ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 54754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 54764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5477a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 54785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 547945d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 54805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 5481d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann final String ftsMatchQuery = SearchIndexManager.getFtsMatchQuery( 5482d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann filterParam, FtsQueryBuilder.UNSCOPED_NORMALIZING); 5483d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann if (ftsMatchQuery.length() > 0) { 5484155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN " + 5485155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 5486155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 5487155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5488155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 5489155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 5490d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann " WHERE " + SearchIndexColumns.NAME + " MATCH '"); 5491d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append(ftsMatchQuery); 5492d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append("')"); 54935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 549445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 54955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 5497892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filterParam); 5498892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (!TextUtils.isEmpty(number)) { 54995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 55005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 55015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 5503892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov " IN (SELECT DISTINCT " + PhoneLookupColumns.DATA_ID 5504892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 5505892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 5506892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append(number); 5507892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append("%')"); 550845d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 550945d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 551045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 551145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 551245d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 551345d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 551445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 55155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 5517a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 5518ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 551958567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa groupBy = "(CASE WHEN " + PhoneColumns.NORMALIZED_NUMBER 552058567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa + " IS NOT NULL THEN " + PhoneColumns.NORMALIZED_NUMBER 552158567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa + " ELSE " + Phone.NUMBER + " END), " + RawContacts.CONTACT_ID; 5522a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 552346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 552446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 552546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + PHONE_FILTER_SORT_ORDER; 552646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 552746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = PHONE_FILTER_SORT_ORDER; 552846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 5529a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 5530ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5531ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5532ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 55334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 553482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55357cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 55367cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail()); 55378ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa 55388ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa final boolean removeDuplicates = readBooleanQueryParameter( 55398ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa uri, ContactsContract.REMOVE_DUPLICATE_ENTRIES, false); 55408ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa if (removeDuplicates) { 55418ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa groupBy = RawContacts.CONTACT_ID + ", " + Data.DATA1; 55428ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa 55438ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa // See PHONES for more detail. 55448ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa addressBookIndexerCountExpression = "DISTINCT " 55458ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa + RawContacts.CONTACT_ID + "||','||" + Data.DATA1; 55468ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa } 55474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 55484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 55494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 555048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 555182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55524da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 55537cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 55547cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail() 55554da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 555648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 555748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 555848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 55595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 556082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55617cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 55627cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail()); 55634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 556408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 55655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String address = mDbHelper.get().extractAddressFromEmailAddress(email); 556608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 556708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 55684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 5569071d0e7bd3b2f3c9628dd655b09d147e668c3931Daniel Lehmann // unless told otherwise, we'll return visible before invisible contacts 5570071d0e7bd3b2f3c9628dd655b09d147e668c3931Daniel Lehmann if (sortOrder == null) { 5571071d0e7bd3b2f3c9628dd655b09d147e668c3931Daniel Lehmann sortOrder = "(" + RawContacts.CONTACT_ID + " IN " + 5572071d0e7bd3b2f3c9628dd655b09d147e668c3931Daniel Lehmann Tables.DEFAULT_DIRECTORY + ") DESC"; 5573071d0e7bd3b2f3c9628dd655b09d147e668c3931Daniel Lehmann } 5574ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5575ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5576ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 55775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 557846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 557946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 558046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 558146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT; 558246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 558346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 558407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 55857d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa 558607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 558707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 558807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 558907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 559007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 559107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 55925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 559307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 559407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 559507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 559607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 559707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 559807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 559907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 560007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 560107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 56022a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "="); 56035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro sb.append(mDbHelper.get().getMimeTypeIdForEmail()); 56042a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(" AND " + Data.DATA1 + " LIKE "); 560507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 560620938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 5607155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append( 5608155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " UNION SELECT " + Data._ID + 5609155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.DATA + 5610155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "="); 56115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro sb.append(mDbHelper.get().getMimeTypeIdForEmail()); 5612155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(" AND " + Data.RAW_CONTACT_ID + " IN " + 5613155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 5614155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 5615155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5616155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 5617155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 5618d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann " WHERE " + SearchIndexColumns.NAME + " MATCH '"); 5619d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann final String ftsMatchQuery = SearchIndexManager.getFtsMatchQuery( 5620d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann filterParam, FtsQueryBuilder.UNSCOPED_NORMALIZING); 5621d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append(ftsMatchQuery); 5622d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append("')"); 56235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 56245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 5625a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 56265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 56275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 5628a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 562946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 563046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 563146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + EMAIL_FILTER_SORT_ORDER; 56327d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } else { 56337d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa sortOrder = EMAIL_FILTER_SORT_ORDER; 56347d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } 5635a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 56365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 56375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 56385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 5639ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 564082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 56417cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 56427cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForStructuredPostal()); 56438ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa 56448ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa final boolean removeDuplicates = readBooleanQueryParameter( 56458ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa uri, ContactsContract.REMOVE_DUPLICATE_ENTRIES, false); 56468ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa if (removeDuplicates) { 56478ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa groupBy = RawContacts.CONTACT_ID + ", " + Data.DATA1; 56488ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa 56498ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa // See PHONES for more detail. 56508ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa addressBookIndexerCountExpression = "DISTINCT " 56518ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa + RawContacts.CONTACT_ID + "||','||" + Data.DATA1; 56528ead0dc62d0031a22af0d14c7ed05893507893c9Daisuke Miyakawa } 5653ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5654ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5655ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 565648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 565782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 56584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 56597cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 56607cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForStructuredPostal()); 56614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 566248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 566348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 566448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 5665d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 5666d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 5667763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 56684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 56694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 56704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 5671d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_ID: 5672d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID: { 56735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 5674763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 56754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 56764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 56774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 56784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 56794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 5680d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 5681d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 5682d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 5683d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(segment)); 568482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 56854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 56864da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 568724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 568824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 568924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 56903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 56913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 56923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 56933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 56943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=?"); 56953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 56963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 569724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 569882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 569982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 570082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro long streamItemId = Long.parseLong(uri.getPathSegments().get(3)); 570182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro setTablesAndProjectionMapForStreamItems(qb); 570282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(streamItemId)); 5703c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 570482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=? AND " + 570582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems._ID + "=?"); 570682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro break; 570782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 570882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 570924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID_ENTITIES: { 571024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(2)); 571124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 571224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForRawEntities(qb, uri); 57135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(" AND " + RawContacts._ID + "=?"); 5714e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 5715e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 5716e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 5717d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case DATA: 5718d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA: { 571982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 5720e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 5721e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 5722e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 5723d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case DATA_ID: 5724d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA_ID: { 572582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 57264da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 57274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 5728a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 5729a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 5730a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 573185077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro case PROFILE_PHOTO: { 573285077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 573385077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 573485077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro break; 573585077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro } 573685077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro 5737a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 5738e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 5739e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 5740e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 574158795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda if (uri.getBooleanQueryParameter(PhoneLookup.QUERY_PARAMETER_SIP_ADDRESS, false)) { 574258795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda if (TextUtils.isEmpty(sortOrder)) { 574358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda // Default the sort order to something reasonable so we get consistent 574458795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda // results when callers don't request an ordering 574558795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda sortOrder = Contacts.DISPLAY_NAME + " ASC"; 574658795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda } 574758795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda 574858795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda String sipAddress = uri.getPathSegments().size() > 1 574958795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda ? Uri.decode(uri.getLastPathSegment()) : ""; 575058795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda setTablesAndProjectionMapForData(qb, uri, null, false, true); 575158795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda StringBuilder sb = new StringBuilder(); 575258795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda selectionArgs = mDbHelper.get().buildSipContactQuery(sb, sipAddress); 575358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda selection = sb.toString(); 575458795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda } else { 575558795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda if (TextUtils.isEmpty(sortOrder)) { 575658795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda // Default the sort order to something reasonable so we get consistent 575758795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda // results when callers don't request an ordering 575858795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda sortOrder = " length(lookup.normalized_number) DESC"; 575958795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda } 576058795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda 576158795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda String number = uri.getPathSegments().size() > 1 576258795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda ? uri.getLastPathSegment() : ""; 576358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda String numberE164 = PhoneNumberUtils.formatNumberToE164(number, 576458795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda mDbHelper.get().getCurrentCountryIso()); 576558795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda String normalizedNumber = 576658795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda PhoneNumberUtils.normalizeNumber(number); 576758795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda mDbHelper.get().buildPhoneLookupAndContactQuery( 576858795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda qb, normalizedNumber, numberE164); 576958795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda qb.setProjectionMap(sPhoneLookupProjectionMap); 577058795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda } 5771a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 5772a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 5773a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5774ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 5775ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 5776ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 5777f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5778ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5779ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5780ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5781ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 5782ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 5783ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 57844da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 57854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 5786ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5787ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5788ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5789ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 5790f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa final boolean returnGroupCountPerAccount = 5791f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa readBooleanQueryParameter(uri, Groups.PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT, 5792f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa false); 579323ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki String tables = Views.GROUPS + " AS " + Tables.GROUPS; 579423ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki if (hasColumn(projection, Groups.SUMMARY_COUNT)) { 579523ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki tables = tables + Joins.GROUP_MEMBER_COUNT; 579623ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki } 579723ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki qb.setTables(tables); 5798f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa qb.setProjectionMap(returnGroupCountPerAccount ? 5799f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa sGroupsSummaryProjectionMapWithGroupCountPerAccount 5800f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa : sGroupsSummaryProjectionMap); 5801f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5802f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa groupBy = GroupsColumns.CONCRETE_ID; 5803ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5804ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5805ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5806b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 58070c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 5808b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 5809b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 5810b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 5811b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 581231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 5813d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 58142d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 58152d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 58162d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 58172d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 581831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 5819d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 5820d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 582131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 582231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 582331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 582431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 58255b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ArrayList<AggregationSuggestionParameter> parameters = null; 58265b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov List<String> query = uri.getQueryParameters("query"); 58275b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov if (query != null && !query.isEmpty()) { 58285b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters = new ArrayList<AggregationSuggestionParameter>(query.size()); 58295b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov for (String parameter : query) { 58305b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov int offset = parameter.indexOf(':'); 58315b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters.add(offset == -1 58325b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ? new AggregationSuggestionParameter( 583376dfa406e2cde19c824983c37fc92c1c5bf63eecDaniel Lehmann AggregationSuggestions.PARAMETER_MATCH_NAME, 58345b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter) 58355b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov : new AggregationSuggestionParameter( 58365b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(0, offset), 58375b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(offset + 1))); 58385b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 58395b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 58405b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 5841763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 58427581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 58435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mAggregator.get().queryAggregationSuggestions(qb, projection, contactId, 58445b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov maxSuggestions, filter, parameters); 584531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 584631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 5847eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 5848eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 5849eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 5850f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5851e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 5852e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 5853e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 58545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final String groupMembershipMimetypeId = Long.toString(mDbHelper.get() 5855e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 585682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 58575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().isInProjection(projection, Settings.UNGROUPED_COUNT)) { 5858e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 5859e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 586082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 58615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().isInProjection( 58625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro projection, Settings.UNGROUPED_WITH_PHONES)) { 5863e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 5864e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 5865e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 5866eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 5867eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 5868eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 58695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 58705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 58710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 58725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 58735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 58745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 587582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 58760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 58774da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 58784da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 58795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 58805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 58815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 5882c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 5883174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery( 58845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get(), uri, projection, limit); 5885c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5886c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 5887c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 58882d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 5889174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String filter = getQueryParameter( 5890174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov uri, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); 5891174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh( 58925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get(), projection, lookupKey, filter); 5893c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5894c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 58953202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro case RAW_CONTACT_ENTITIES: 58963202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro case PROFILE_RAW_CONTACT_ENTITIES: { 5897a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 589846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 589946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 590046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 590146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 590246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 5903a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 59044da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 59054da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 590646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 590746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 590846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 590909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 591009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 591109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 591209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5913d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES : { 5914d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5915d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5916d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5917d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5918d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 5919d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID : { 5920385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov long id = ContentUris.parseId(uri); 5921d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5922d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5923385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(id)); 5924d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Directory._ID + "=?"); 5925d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5926d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5927d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 59287a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov case COMPLETE_NAME: { 59297a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return completeName(uri, projection); 59307a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 59317a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 59324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 5933f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 5934c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 59354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 59364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 593709e69522745551522c55dff27424496f255def46Daniel Lehmann qb.setStrict(true); 59387f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 5939ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 59405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro query(mActiveDb.get(), qb, projection, selection, selectionArgs, sortOrder, groupBy, 59415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro limit); 5942ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 59435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cursor = bundleLetterCountExtras(cursor, mActiveDb.get(), qb, selection, 59442ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki selectionArgs, sortOrder, addressBookIndexerCountExpression); 5945ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5946b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (snippetDeferred) { 5947b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson cursor = addDeferredSnippetingExtra(cursor); 5948b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 5949ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 59505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 59515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 59525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 59535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 59545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 5955038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 5956038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 5957038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 5958038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 59595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 59605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 59614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 59624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 59634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 59644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 59654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 59664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 596709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 596809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 596909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 597009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 597109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 597209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 597309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 597409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 597509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 597609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 597709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 597809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 597909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 598009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 598109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 598209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5983a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 5984a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Runs the query with the supplied contact ID and lookup ID. If the query succeeds, 5985a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * it returns the resulting cursor, otherwise it returns null and the calling 5986a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * method needs to resolve the lookup key and rerun the query. 5987a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 5988a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private Cursor queryWithContactIdAndLookupKey(SQLiteQueryBuilder lookupQb, 5989a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteDatabase db, Uri uri, 5990a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection, String selection, String[] selectionArgs, 5991a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String sortOrder, String groupBy, String limit, 5992a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn, long contactId, String lookupKeyColumn, String lookupKey) { 5993a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] args; 5994a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (selectionArgs == null) { 5995a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[2]; 5996a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 5997a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[selectionArgs.length + 2]; 5998a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 5999a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6000a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[0] = String.valueOf(contactId); 6001a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[1] = Uri.encode(lookupKey); 6002a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(contactIdColumn + "=? AND " + lookupKeyColumn + "=?"); 6003a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 6004a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov groupBy, limit); 6005a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c.getCount() != 0) { 6006a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 6007a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6008a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6009a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov c.close(); 6010a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return null; 6011a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 601209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 6013bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 6014bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 6015bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 6016bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 6017ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6018bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 6019bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 6020ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 6021ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6022bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 6023bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 6024bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 6025bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 60265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // The first letter of the sort key column is what is used for the index headings. 60275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public static final String SECTION_HEADING = "SUBSTR(%1$s,1,1)"; 602824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 6029de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 6030ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6031ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6032ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 6033ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 6034ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 6035ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 6036ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 60372ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder, 60382ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki String countExpression) { 6039409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki if (!(cursor instanceof AbstractCursor)) { 6040409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki Log.w(TAG, "Unable to bundle extras. Cursor is not AbstractCursor."); 6041409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki return cursor; 6042409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki } 6043ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 6044ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6045ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 6046ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 6047ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 6048ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 6049ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 6050ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 6051ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 6052ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 6053ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 6054ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 6055ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 6056ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6057ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 6058ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 6059ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6060ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6061bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 6062ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 60635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String sectionHeading = String.format(AddressBookIndexQuery.SECTION_HEADING, sortKey); 6064bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 606524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro sectionHeading + " AS " + AddressBookIndexQuery.LETTER); 6066bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 60672ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // If "what to count" is not specified, we just count all records. 60682ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki if (TextUtils.isEmpty(countExpression)) { 60692ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki countExpression = "*"; 60702ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki } 60712ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 6072bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 6073bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 6074bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 6075bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 6076bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 6077bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 6078bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 6079ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 608024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "GET_PHONEBOOK_INDEX(" + sectionHeading + ",'" + locale + "')" 6081bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 6082ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 60832ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki "COUNT(" + countExpression + ") AS " + AddressBookIndexQuery.COUNT); 6084ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 6085ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6086f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 6087ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 6088ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 6089ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6090ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 6091f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 6092ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 6093ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 6094bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 6095bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 6096bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 6097bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 6098bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 6099bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 6100ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 6101f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 6102bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 6103bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 6104bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 6105bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 6106bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 6107bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 6108bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 6109bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 6110bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 6111bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 6112bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 6113bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 6114bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 6115bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 6116bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 6117bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 6118bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 6119bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 6120bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 6121ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6122ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6123409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki final Bundle bundle = new Bundle(); 6124409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 6125409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 6126409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki 6127409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki ((AbstractCursor) cursor).setExtras(bundle); 6128409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki return cursor; 6129ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 6130f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 6131ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6132ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6133ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 61342d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 613592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 613692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 613792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 613892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 61392d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 61402d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 61415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 61425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 61435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 614492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 61455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_PROFILE)) { 61465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // We should already be in a profile database context, so just look up a single contact. 61475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro contactId = lookupSingleContactId(db); 61485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 61495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 615092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 615192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 615292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 615392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 615492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 615592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 615692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 615792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 615892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 615992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 616092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 616192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 616292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 616392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 616492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 616592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 616692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 616792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 61685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 61695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 61725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private long lookupSingleContactId(SQLiteDatabase db) { 61755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = db.query(Tables.CONTACTS, new String[] {Contacts._ID}, 61765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null, null, null, null, null, "1"); 61775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro try { 61785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (c.moveToFirst()) { 61795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return c.getLong(0); 61805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 61815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return -1; 61825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 61835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } finally { 61845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c.close(); 61855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 61865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 61875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 61885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 618943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String TABLE = Views.RAW_CONTACTS; 61905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 61925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 619343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 61945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 61955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 61965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 61975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 619943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 62005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 62015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 62025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 62055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 62065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 62075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 62085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 62095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 621092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 62115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 62125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 62135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 62165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 62175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 62195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 62205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 62215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 622243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = 622343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE_AND_DATA_SET); 62245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 62255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 622643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 62275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 62285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 62295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 623092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 623192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 62325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 62335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 62345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 62355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 62395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 62405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 62435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 624592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 624643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String TABLE = Views.RAW_CONTACTS; 62475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 62495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 625043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 62515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 625292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 62535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 62545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 625643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 62575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 625892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 62595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 626192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 626292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 626392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 626492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 62655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 62665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 626792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 626892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 626992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 62705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 627292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 627392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 62745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 627592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 627692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 627792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 627892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 627943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = c.getString( 628043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro LookupByRawContactIdQuery.ACCOUNT_TYPE_AND_DATA_SET); 628192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 628292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 628343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 628492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 628592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 628692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 628792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 628892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 628992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 629092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 629192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 629292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 629392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 629492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 629592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 629692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 62975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 629992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 630092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 630192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 630292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 630392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 630492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 630592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 630692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 630743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 630892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 630992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 631092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 631192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 631292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 631343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 631492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 631592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 631692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 631792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 631892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 631992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 63205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 63215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 63225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 63235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 632492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 632592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 63265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 63275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 63285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 63315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 63325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 63335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 63345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 63355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 63365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 63375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 633843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = 633943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE_AND_DATA_SET); 63405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 63415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 634243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 63435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 63445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 63455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 634692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 634792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 634892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 63495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 63505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 63515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 63525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 63565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 63575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 63595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 63605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 636292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 636392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 636492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 636592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 636692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 636792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 636892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 636992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 637092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 637192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 637292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 6373ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 63745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLookupKeyForRawContact(db, rawContactId); 6375ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 6376ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 63775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 63785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 63795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 63805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 63815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 63825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 63835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 63845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 63855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 63865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 63875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 63885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 63895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 63905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 63915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 63925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 63935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 63945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 63955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 63965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 63975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 63985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 63995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 64005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 64015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 64025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 64035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 64045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 64055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 64065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 64075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 64085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 64095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 64105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 64115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 6412763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 6413763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 64144928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false); 64152f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 64162f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 64172f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 64184928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * @param includeDataUsageStat true when the table should include DataUsageStat table. 64194928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Note that this uses INNER JOIN instead of LEFT OUTER JOIN, so some of data in Contacts 64204928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * may be dropped. 64212f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 64222f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 64234928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa String[] projection, boolean includeDataUsageStat) { 642482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6425ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 64262f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 64272f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Just for frequently contacted contacts in Strequent Uri handling. 64284928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa if (includeDataUsageStat) { 64292f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa sb.append(" INNER JOIN " + 6430ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA_USAGE_STAT + " AS " + Tables.DATA_USAGE_STAT + 64312f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa " ON (" + 64322f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DbQueryUtils.concatenateClauses( 64332f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DataUsageStatColumns.CONCRETE_TIMES_USED + " > 0", 64344928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa RawContacts.CONTACT_ID + "=" + Views.CONTACTS + "." + Contacts._ID) + 64352f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa ")"); 64362f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 64372f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 64387ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 64397ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6440916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 6441916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 6442916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 6443916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6444916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 6445916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 6446916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 6447916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 6448916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 6449b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson String[] projection, String filter, long directoryId, boolean deferredSnippeting) { 64507ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov 64517ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 6452ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 6453916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 645403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (filter != null) { 645503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov filter = filter.trim(); 645603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 645703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 645830cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov if (TextUtils.isEmpty(filter) || (directoryId != -1 && directoryId != Directory.DEFAULT)) { 645930cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov sb.append(" JOIN (SELECT NULL AS " + SearchSnippetColumns.SNIPPET + " WHERE 0)"); 64605e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } else { 6461b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson appendSearchIndexJoin(sb, uri, projection, filter, deferredSnippeting); 64625e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 64637ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 64647ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 646503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setTables(sb.toString()); 646603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 646703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 6468916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 646903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private void appendSearchIndexJoin( 6470b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson StringBuilder sb, Uri uri, String[] projection, String filter, 6471b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean deferredSnippeting) { 6472916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6473b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (snippetNeeded(projection)) { 647403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String[] args = null; 647503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String snippetArgs = 647603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 647703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (snippetArgs != null) { 647803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov args = snippetArgs.split(","); 647903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 648003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 64815e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String startMatch = args != null && args.length > 0 ? args[0] 64825e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_START_MATCH; 64835e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String endMatch = args != null && args.length > 1 ? args[1] 64845e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_END_MATCH; 64855e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String ellipsis = args != null && args.length > 2 ? args[2] 64865e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_ELLIPSIS; 64875e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 64885e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 64895e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 6490174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov appendSearchIndexJoin( 6491b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson sb, filter, true, startMatch, endMatch, ellipsis, maxTokens, 6492b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnippeting); 6493174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 6494b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson appendSearchIndexJoin(sb, filter, false, null, null, null, 0, false); 6495174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6496174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6497174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 6498174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov public void appendSearchIndexJoin(StringBuilder sb, String filter, 6499174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean snippetNeeded, String startMatch, String endMatch, String ellipsis, 6500b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson int maxTokens, boolean deferredSnippeting) { 6501174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isEmailAddress = false; 6502174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String emailAddress = null; 6503174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isPhoneNumber = false; 6504174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String phoneNumber = null; 6505174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String numberE164 = null; 6506174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 65073716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // If the query consists of a single word, we can do snippetizing after-the-fact for a 65083716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // performance boost. 6509b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean singleTokenSearch = isSingleWordQuery(filter); 65103716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6511174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (filter.indexOf('@') != -1) { 65125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro emailAddress = mDbHelper.get().extractAddressFromEmailAddress(filter); 6513174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isEmailAddress = !TextUtils.isEmpty(emailAddress); 6514174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 6515174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isPhoneNumber = isPhoneNumber(filter); 651604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (isPhoneNumber) { 651704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann phoneNumber = PhoneNumberUtils.normalizeNumber(filter); 651804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann numberE164 = PhoneNumberUtils.formatNumberToE164(phoneNumber, 65195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getCountryIso()); 652004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 6521174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6522174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 6523d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann final String SNIPPET_CONTACT_ID = "snippet_contact_id"; 6524d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append(" JOIN (SELECT " + SearchIndexColumns.CONTACT_ID + " AS " + SNIPPET_CONTACT_ID); 6525174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (snippetNeeded) { 65265e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(", "); 65275e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 65283d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 65295e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 653004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Email.ADDRESS + ")"); 653104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS); 653204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 653304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID + " AND " + Email.ADDRESS + " LIKE "); 653404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann DatabaseUtils.appendEscapedSQLString(sb, filter + "%"); 653504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 65363d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 65373d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(","); 65383716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6539b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested). 6540b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 65413716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 65423716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 65433716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 65443716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 65453d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(")"); 65463d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 65473d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 65483d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 654904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Phone.NUMBER + ")"); 655004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + 655104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann Tables.DATA_JOIN_RAW_CONTACTS + " JOIN " + Tables.PHONE_LOOKUP); 655204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" ON " + DataColumns.CONCRETE_ID); 655304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + Tables.PHONE_LOOKUP + "." + PhoneLookupColumns.DATA_ID); 655404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 655504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID); 655604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" AND " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 655704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(phoneNumber); 655804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 655904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(numberE164)) { 656004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" OR " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 656104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(numberE164); 656204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 656304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 656404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 65655e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 65665e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 65673716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6568b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested). 6569b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 65703716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 65713716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 65723716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 65733716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 65745e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 657503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 657604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann final String normalizedFilter = NameNormalizer.normalize(filter); 657704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(normalizedFilter)) { 6578b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested).. 6579b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 65803716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 65813716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 65823716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("(CASE WHEN EXISTS (SELECT 1 FROM "); 65833716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.RAW_CONTACTS + " AS rc INNER JOIN "); 65843716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.NAME_LOOKUP + " AS nl ON (rc." + RawContacts._ID); 65853716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=nl." + NameLookupColumns.RAW_CONTACT_ID); 65863716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") WHERE nl." + NameLookupColumns.NORMALIZED_NAME); 65873716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" GLOB '" + normalizedFilter + "*' AND "); 65883716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("nl." + NameLookupColumns.NAME_TYPE + "="); 65893716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(NameLookupType.NAME_COLLATION_KEY + " AND "); 65903716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 65913716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=rc." + RawContacts.CONTACT_ID); 65923716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") THEN NULL ELSE "); 65933716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 65943716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" END)"); 65953716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 659604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } else { 659704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("NULL"); 659804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 659903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 66005e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" AS " + SearchSnippetColumns.SNIPPET); 66015e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 660203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 66035e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" FROM " + Tables.SEARCH_INDEX); 66045e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" WHERE "); 6605d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append(Tables.SEARCH_INDEX + " MATCH '"); 66065e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 6607d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann // we know that the emailAddress contains a @. This phrase search should be 6608d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann // scoped against "content:" only, but unfortunately SQLite doesn't support 6609d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann // phrases and scoped columns at once. This is fine in this case however, because: 6610d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann // - We can't erronously match against name, as name is all-hex (so the @ can't match) 6611d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann // - We can't match against tokens, because phone-numbers can't contain @ 6612d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann final String sanitizedEmailAddress = 6613d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann emailAddress == null ? "" : sanitizeMatch(emailAddress); 6614d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append("\""); 6615d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append(sanitizedEmailAddress); 6616d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append("*\""); 66173d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 6618d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann // normalized version of the phone number (phoneNumber can only have + and digits) 6619d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann final String phoneNumberCriteria = " OR tokens:" + phoneNumber + "*"; 6620d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann 6621d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann // international version of this number (numberE164 can only have + and digits) 6622d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann final String numberE164Criteria = 6623d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann (numberE164 != null && !TextUtils.equals(numberE164, phoneNumber)) 6624d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann ? " OR tokens:" + numberE164 + "*" 6625d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann : ""; 6626d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann 6627d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann // combine all criteria 6628d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann final String commonCriteria = 6629d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann phoneNumberCriteria + numberE164Criteria; 6630d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann 6631d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann // search in content 6632d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append(SearchIndexManager.getFtsMatchQuery(filter, 6633d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann FtsQueryBuilder.getDigitsQueryBuilder(commonCriteria))); 663403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 6635d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann // general case: not a phone number, not an email-address 6636d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann sb.append(SearchIndexManager.getFtsMatchQuery(filter, 6637d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann FtsQueryBuilder.SCOPED_NAME_NORMALIZING)); 66389c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 66391322df8f90d80587748ad10539516635326c01e8Daniel Lehmann // Omit results in "Other Contacts". 66401322df8f90d80587748ad10539516635326c01e8Daniel Lehmann sb.append("' AND " + SNIPPET_CONTACT_ID + " IN " + Tables.DEFAULT_DIRECTORY + ")"); 66411322df8f90d80587748ad10539516635326c01e8Daniel Lehmann sb.append(" ON (" + Contacts._ID + "=" + SNIPPET_CONTACT_ID + ")"); 6642a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov } 6643a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov 6644d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann private static String sanitizeMatch(String filter) { 6645d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann return filter.replace("'", "").replace("*", "").replace("-", "").replace("\"", ""); 66462352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov } 66472352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov 66485e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov private void appendSnippetFunction( 66495e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov StringBuilder sb, String startMatch, String endMatch, String ellipsis, int maxTokens) { 66505e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append("snippet(" + Tables.SEARCH_INDEX + ","); 66515e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 66525e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 66535e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 66545e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 66555e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, ellipsis); 66565e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 66575e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov // The index of the column used for the snippet, "content" 66585e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(",1,"); 66595e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(maxTokens); 66605e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 66615e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 66625e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 6663763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 6664763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 6665ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.RAW_CONTACTS); 6666763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 6667763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 6668f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6669763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 6670763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 6671a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForRawEntities(SQLiteQueryBuilder qb, Uri uri) { 6672ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.RAW_ENTITIES); 6673a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sRawEntityProjectionMap); 6674f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 667546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 667646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 667782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 667882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 667958795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda setTablesAndProjectionMapForData(qb, uri, projection, distinct, false, null); 668058795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda } 668158795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda 668258795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 668358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda String[] projection, boolean distinct, boolean addSipLookupColumns) { 668458795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda setTablesAndProjectionMapForData(qb, uri, projection, distinct, addSipLookupColumns, null); 668546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 668646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 668746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 668846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @param usageType when non-null {@link Tables#DATA_USAGE_STAT} is joined with the specified 668946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type. 669046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 669146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 669246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String[] projection, boolean distinct, Integer usageType) { 669358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda setTablesAndProjectionMapForData(qb, uri, projection, distinct, false, usageType); 669458795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda } 669558795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda 669658795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 669758795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda String[] projection, boolean distinct, boolean addSipLookupColumns, Integer usageType) { 669882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6699ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 670082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 670182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 6702a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, RawContacts.CONTACT_ID); 6703a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6704a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 6705a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 67063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 670746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (usageType != null) { 670846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa appendDataUsageStatJoin(sb, usageType, DataColumns.CONCRETE_ID); 670946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 671046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 671182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 6712f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 6713f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov boolean useDistinct = distinct 67145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro || !mDbHelper.get().isInProjection(projection, DISTINCT_DATA_PROHIBITING_COLUMNS); 6715f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setDistinct(useDistinct); 671658795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda 671758795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda final ProjectionMap projectionMap; 671858795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda if (addSipLookupColumns) { 671958795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda projectionMap = useDistinct 672058795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda ? sDistinctDataSipLookupProjectionMap : sDataSipLookupProjectionMap; 672158795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda } else { 672258795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda projectionMap = useDistinct ? sDistinctDataProjectionMap : sDataProjectionMap; 672358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda } 672458795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda 672558795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda qb.setProjectionMap(projectionMap); 6726f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6727ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 6728ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 67290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 67300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 67310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6732ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 67330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 6734a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 6735a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 67360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 6737a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 6738a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 6739a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6740a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 67413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItems(SQLiteQueryBuilder qb) { 67429b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann qb.setTables(Views.STREAM_ITEMS); 67433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemsProjectionMap); 67443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 67453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 67463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItemPhotos(SQLiteQueryBuilder qb) { 67471dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro qb.setTables(Tables.PHOTO_FILES 67481dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + " JOIN " + Tables.STREAM_ITEM_PHOTOS + " ON (" 67491dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + StreamItemPhotosColumns.CONCRETE_PHOTO_FILE_ID + "=" 67501dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + PhotoFilesColumns.CONCRETE_ID 67511dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + ") JOIN " + Tables.STREAM_ITEMS + " ON (" 67521dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=" 67530bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + StreamItemsColumns.CONCRETE_ID + ")" 67540bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + " JOIN " + Tables.RAW_CONTACTS + " ON (" 67550bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + StreamItemsColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID 67560bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + ")"); 67573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemPhotosProjectionMap); 67583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 67593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 6760a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForEntities(SQLiteQueryBuilder qb, Uri uri, 6761a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection) { 6762a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 6763ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.ENTITIES); 6764a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" data"); 6765a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6766a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts.Entity.CONTACT_ID); 6767a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6768a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, Contacts.Entity.DATA_ID); 6769a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, Contacts.Entity.DATA_ID); 6770a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6771a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 6772a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sEntityProjectionMap); 6773f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6774a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6775a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6776a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactStatusUpdateJoin(StringBuilder sb, String[] projection, 6777a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lastStatusUpdateIdColumn) { 67785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 6779a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS, 6780a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 6781a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 6782a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 6783a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 6784a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 6785a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 6786a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + lastStatusUpdateIdColumn + "=" 6787a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 67880a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 6789a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 67900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 6791a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataStatusUpdateJoin(StringBuilder sb, String[] projection, 6792a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 67935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 67940a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 67950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 67960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 67970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 67980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 67990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 6800a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 6801a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + dataIdColumn + ")"); 68020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 6803a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6804a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 680546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void appendDataUsageStatJoin(StringBuilder sb, int usageType, String dataIdColumn) { 680646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" LEFT OUTER JOIN " + Tables.DATA_USAGE_STAT + 680746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" + dataIdColumn + 680846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " AND " + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" + usageType + ")"); 680946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 681046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 6811a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactPresenceJoin(StringBuilder sb, String[] projection, 6812a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn) { 68135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 6814a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_PRESENCE, Contacts.CONTACT_CHAT_CAPABILITY)) { 6815a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 6816a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + contactIdColumn + " = " 6817a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + ")"); 6818a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6819a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6820a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6821a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataPresenceJoin(StringBuilder sb, String[] projection, 6822a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 68235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, Data.PRESENCE, Data.CHAT_CAPABILITY)) { 6824a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 6825a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdates.DATA_ID + "=" + dataIdColumn + ")"); 6826a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6827a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6828a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 682924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private boolean appendLocalDirectorySelectionIfNeeded(SQLiteQueryBuilder qb, long directoryId) { 6830385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directoryId == Directory.DEFAULT) { 6831385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " IN " + Tables.DEFAULT_DIRECTORY); 683224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 6833385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directoryId == Directory.LOCAL_INVISIBLE){ 6834385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " NOT IN " + Tables.DEFAULT_DIRECTORY); 683524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 683624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 683724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return false; 683824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 683924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 6840f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 6841f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 6842f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 684343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro final String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 6844e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6845e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 6846e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 6847e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 68485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6849fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 6850e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 6851e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6852e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 6853e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 6854e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 6855e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 685643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String toAppend = RawContacts.ACCOUNT_NAME + "=" 68574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 68584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 685943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + DatabaseUtils.sqlEscapeString(accountType); 6860f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet == null) { 6861f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro toAppend += " AND " + RawContacts.DATA_SET + " IS NULL"; 6862f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } else { 6863f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro toAppend += " AND " + RawContacts.DATA_SET + "=" + 6864f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro DatabaseUtils.sqlEscapeString(dataSet); 686543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 686643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro qb.appendWhere(toAppend); 68674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 68684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 68694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 68704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 68714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 6872e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 6873f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 6874f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 687543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro final String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 6876e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6877e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 6878e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 6879e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 68805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6881fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 6882e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 6883e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6884e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 6885e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 6886e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 6887e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 6888e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 6889e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 6890e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 6891e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 6892f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet == null) { 6893f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro selectionSb.append(" AND " + RawContacts.DATA_SET + " IS NULL"); 6894f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } else { 689543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro selectionSb.append(" AND " + RawContacts.DATA_SET + "=") 689643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .append(DatabaseUtils.sqlEscapeString(dataSet)); 689743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 6898e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 6899e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 6900e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 6901e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 6902e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6903e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 6904e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 6905e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 6906e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6907e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6908e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 69097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 6910c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 6911c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 6912c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 6913c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 6914c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 6915f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 69162e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limitParam = getQueryParameter(uri, ContactsContract.LIMIT_PARAM_KEY); 6917c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 6918c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6919c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6920c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 6921c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 6922c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 6923c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 6924c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 6925c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6926c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6927c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 6928c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 6929c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 6930c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6931c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6932c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6933c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 6934b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 6935f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 6936f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (mode.equals("r")) { 6937f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro waitForAccess(mReadAccessLatch); 6938f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 6939f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro waitForAccess(mWriteAccessLatch); 6940f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 69415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 69425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 69435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileProvider.openAssetFile(uri, mode); 69445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 69455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 69465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openAssetFileLocal(uri, mode); 69475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 69485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 69495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 69505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public AssetFileDescriptor openAssetFileLocal(Uri uri, String mode) 69515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throws FileNotFoundException { 69525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 69535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 69545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 6955078f588cef389358adabc579de00747878f3c108Dave Santoro if (mode.equals("r")) { 6956078f588cef389358adabc579de00747878f3c108Dave Santoro mActiveDb.set(mContactsHelper.getReadableDatabase()); 6957078f588cef389358adabc579de00747878f3c108Dave Santoro } else { 6958078f588cef389358adabc579de00747878f3c108Dave Santoro mActiveDb.set(mContactsHelper.getWritableDatabase()); 6959078f588cef389358adabc579de00747878f3c108Dave Santoro } 69605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 6961415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 6962b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 6963b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 6964a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 6965bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long contactId = Long.parseLong(uri.getPathSegments().get(1)); 69665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 696724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Data._ID + "=" + Contacts.PHOTO_ID + " AND " + 696824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro RawContacts.CONTACT_ID + "=?", 6969bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro new String[]{String.valueOf(contactId)}); 6970e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 6971b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 6972f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_ID_DISPLAY_PHOTO: { 6973f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6974f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6975f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by contact ID can only be read."); 6976f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6977f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long contactId = Long.parseLong(uri.getPathSegments().get(1)); 69785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.CONTACTS, 6979f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{Contacts.PHOTO_FILE_ID}, 6980f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Contacts._ID + "=?", new String[]{String.valueOf(contactId)}, 6981f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro null, null, null); 6982f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 698385077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro if (c.moveToFirst()) { 698485077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro long photoFileId = c.getLong(0); 698585077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro return openDisplayPhotoForRead(photoFileId); 698685077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro } else { 698785077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro // No contact for this ID. 698885077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro throw new FileNotFoundException(uri.toString()); 698985077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro } 699085077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro } finally { 699185077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro c.close(); 699285077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro } 699385077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro } 699485077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro 699585077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro case PROFILE_DISPLAY_PHOTO: { 699685077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro if (!mode.equals("r")) { 699785077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro throw new IllegalArgumentException( 699885077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro "Display photos retrieved by contact ID can only be read."); 699985077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro } 700085077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro Cursor c = mActiveDb.get().query(Tables.CONTACTS, 700185077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro new String[]{Contacts.PHOTO_FILE_ID}, null, null, null, null, null); 700285077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro try { 700385077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro if (c.moveToFirst()) { 700485077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro long photoFileId = c.getLong(0); 700585077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro return openDisplayPhotoForRead(photoFileId); 700685077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro } else { 700785077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro // No profile record. 700885077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro throw new FileNotFoundException(uri.toString()); 700985077339f2e0c6f21fd92fb8df335f3aae004fbaDave Santoro } 7010f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 7011f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 7012f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7013f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7014f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7015bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_PHOTO: 7016bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_PHOTO: 7017f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_DISPLAY_PHOTO: 7018f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_ID_DISPLAY_PHOTO: { 7019f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 7020f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 7021bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro "Photos retrieved by contact lookup key can only be read."); 7022f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7023f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro List<String> pathSegments = uri.getPathSegments(); 7024f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro int segmentCount = pathSegments.size(); 7025f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (segmentCount < 4) { 70265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 7027f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Missing a lookup key", uri)); 7028f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7029bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro 7030bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro boolean forDisplayPhoto = (match == CONTACTS_LOOKUP_ID_DISPLAY_PHOTO 7031bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro || match == CONTACTS_LOOKUP_DISPLAY_PHOTO); 7032f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String lookupKey = pathSegments.get(2); 7033bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro String[] projection = new String[]{Contacts.PHOTO_ID, Contacts.PHOTO_FILE_ID}; 7034f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (segmentCount == 5) { 7035f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long contactId = Long.parseLong(pathSegments.get(3)); 7036f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 7037f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 70385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 7039f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro projection, null, null, null, null, null, 7040f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 7041f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (c != null) { 7042f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7043f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 7044bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (forDisplayPhoto) { 7045bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoFileId = 7046bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro c.getLong(c.getColumnIndex(Contacts.PHOTO_FILE_ID)); 7047bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openDisplayPhotoForRead(photoFileId); 7048bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } else { 7049bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoId = c.getLong(c.getColumnIndex(Contacts.PHOTO_ID)); 7050bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 7051bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro Data._ID + "=?", new String[]{String.valueOf(photoId)}); 7052bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 7053f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 7054f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 7055f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7056f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7057f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7058f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7059f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 7060f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 70615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 70625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), projection, Contacts._ID + "=?", 7063f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{String.valueOf(contactId)}, null, null, null); 7064f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7065f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 7066bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (forDisplayPhoto) { 7067bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoFileId = c.getLong(c.getColumnIndex(Contacts.PHOTO_FILE_ID)); 7068bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openDisplayPhotoForRead(photoFileId); 7069bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } else { 7070bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoId = c.getLong(c.getColumnIndex(Contacts.PHOTO_ID)); 7071bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 7072bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro Data._ID + "=?", new String[]{String.valueOf(photoId)}); 7073bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 7074f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 7075f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 7076f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7077f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7078f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7079f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case RAW_CONTACTS_ID_DISPLAY_PHOTO: { 7080f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 7081f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro boolean writeable = !mode.equals("r"); 7082f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7083f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Find the primary photo data record for this raw contact. 7084f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 7085f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String[] projection = new String[]{Data._ID, Photo.PHOTO_FILE_ID}; 7086f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 70877cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 70885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), projection, 70897cf50494501938f175d288077145acf49da8f171Daniel Lehmann Data.RAW_CONTACT_ID + "=? AND " + DataColumns.MIMETYPE_ID + "=?", 70907cf50494501938f175d288077145acf49da8f171Daniel Lehmann new String[]{String.valueOf(rawContactId), String.valueOf(photoMimetypeId)}, 7091f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro null, null, Data.IS_PRIMARY + " DESC"); 7092f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long dataId = 0; 7093f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = 0; 7094f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7095f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (c.getCount() >= 1) { 7096f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 7097f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro dataId = c.getLong(0); 7098f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro photoFileId = c.getLong(1); 7099f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7100f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 7101f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 7102f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7103f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7104f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // If writeable, open a writeable file descriptor that we can monitor. 7105f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // When the caller finishes writing content, we'll process the photo and 7106f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // update the data record. 7107f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (writeable) { 7108f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForWrite(rawContactId, dataId, uri, mode); 7109f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 7110f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 7111f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7112f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7113f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7114f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case DISPLAY_PHOTO: { 7115f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = ContentUris.parseId(uri); 7116f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 7117f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 7118f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by key can only be read."); 7119f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7120f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 7121f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7122f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7123e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 712424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long dataId = Long.parseLong(uri.getPathSegments().get(1)); 71257cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 71265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 71277cf50494501938f175d288077145acf49da8f171Daniel Lehmann Data._ID + "=? AND " + DataColumns.MIMETYPE_ID + "=" + photoMimetypeId, 712824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro new String[]{String.valueOf(dataId)}); 7129d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7130d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7131fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case PROFILE_AS_VCARD: { 7132fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // When opening a contact as file, we pass back contents as a 7133fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // vCard-encoded stream. We build into a local buffer first, 7134fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // then pipe into MemoryFile once the exact size is known. 7135fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 7136fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 7137fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen return buildAssetFileDescriptor(localStream); 7138fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen } 713942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 7140fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case CONTACTS_AS_VCARD: { 714142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 714242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 714342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 714442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 7145fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 7146f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 714742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 714842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 714942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 715042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 715142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 715242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 7153fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Uri queryUri = Contacts.CONTENT_URI; 715442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 7155fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen 7156d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 7157d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 715842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 715942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 7160d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 716142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 7162d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 716342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 71645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // TODO: Figure out what to do if the profile contact is in the list. 71655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 716624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro inBuilder.append(contactId); 716742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 716842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 716942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 717042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 7171d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7172d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 7173d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 7174d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 7175d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 7176fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(queryUri, localStream, selection, null); 7177f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 7178d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7179b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 7180b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 71815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new FileNotFoundException(mDbHelper.get().exceptionMessage( 71825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "File does not exist", uri)); 7183b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 7184b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 7185b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 7186afc8e7ad6e5208db6c87b8500ecc1246ad966d62Dave Santoro private AssetFileDescriptor openPhotoAssetFile(SQLiteDatabase db, Uri uri, String mode, 7187afc8e7ad6e5208db6c87b8500ecc1246ad966d62Dave Santoro String selection, String[] selectionArgs) 7188e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 7189e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 71905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new FileNotFoundException(mDbHelper.get().exceptionMessage("Mode " + mode 7191e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 7192e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 7193e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 7194e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 7195ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann "SELECT " + Photo.PHOTO + " FROM " + Views.DATA + 7196e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 719708ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood try { 7198f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 7199f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert DatabaseUtils.blobFileDescriptorForQuery(db, sql, selectionArgs)); 720008ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } catch (SQLiteDoneException e) { 720108ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood // this will happen if the DB query returns no rows (i.e. contact does not exist) 720208ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood throw new FileNotFoundException(uri.toString()); 720308ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } 7204e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 7205e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 7206f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7207f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Opens a display photo from the photo store for reading. 7208f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param photoFileId The display photo file ID 7209f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @return An asset file descriptor that allows the file to be read. 7210f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @throws FileNotFoundException If no photo file for the given ID exists. 7211f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7212f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private AssetFileDescriptor openDisplayPhotoForRead(long photoFileId) 7213f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throws FileNotFoundException { 72145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore.Entry entry = mPhotoStore.get().get(photoFileId); 7215f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (entry != null) { 7216d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro try { 7217d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro return makeAssetFileDescriptor( 7218d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro ParcelFileDescriptor.open(new File(entry.path), 7219d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro ParcelFileDescriptor.MODE_READ_ONLY), 7220d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro entry.size); 7221d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro } catch (FileNotFoundException fnfe) { 7222d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 7223d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro throw fnfe; 7224d9125effce84804631c8e618ae88b2cfc69cf529Dave Santoro } 7225f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 7226f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 7227f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new FileNotFoundException("No photo file found for ID " + photoFileId); 7228f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7229f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7230f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7231f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7232f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Opens a file descriptor for a photo to be written. When the caller completes writing 7233f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * to the file (closing the output stream), the image will be parsed out and processed. 7234f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * If processing succeeds, the given raw contact ID's primary photo record will be 7235f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * populated with the inserted image (if no primary photo record exists, the data ID can 7236f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * be left as 0, and a new data record will be inserted). 7237f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param rawContactId Raw contact ID this photo entry should be associated with. 7238f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param dataId Data ID for a photo mimetype that will be updated with the inserted 7239f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * image. May be set to 0, in which case the inserted image will trigger creation 7240f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * of a new primary photo image data row for the raw contact. 7241f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param uri The URI being used to access this file. 7242f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param mode Read/write mode string. 7243f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @return An asset file descriptor the caller can use to write an image file for the 7244f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * raw contact. 7245f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7246f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private AssetFileDescriptor openDisplayPhotoForWrite(long rawContactId, long dataId, Uri uri, 7247f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String mode) { 7248f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7249c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro ParcelFileDescriptor[] pipeFds = ParcelFileDescriptor.createPipe(); 7250c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro PipeMonitor pipeMonitor = new PipeMonitor(rawContactId, dataId, pipeFds[0]); 7251c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro pipeMonitor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[]) null); 7252c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro return new AssetFileDescriptor(pipeFds[1], 0, AssetFileDescriptor.UNKNOWN_LENGTH); 7253f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } catch (IOException ioe) { 7254f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Log.e(TAG, "Could not create temp image file in mode " + mode); 7255f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return null; 7256f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7257f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7258f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7259f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7260c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * Async task that monitors the given file descriptor (the read end of a pipe) for 7261c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * the writer finishing. If the data from the pipe contains a valid image, the image 7262c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * is either inserted into the given raw contact or updated in the given data row. 7263f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7264c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private class PipeMonitor extends AsyncTask<Object, Object, Object> { 7265c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private final ParcelFileDescriptor mDescriptor; 7266f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private final long mRawContactId; 7267f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private final long mDataId; 7268c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private PipeMonitor(long rawContactId, long dataId, ParcelFileDescriptor descriptor) { 7269f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mRawContactId = rawContactId; 7270f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mDataId = dataId; 7271c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro mDescriptor = descriptor; 7272f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7273f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7274f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro @Override 7275c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro protected Object doInBackground(Object... params) { 7276c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro AutoCloseInputStream is = new AutoCloseInputStream(mDescriptor); 7277f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7278c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro Bitmap b = BitmapFactory.decodeStream(is); 7279f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (b != null) { 7280fa4db3db4146a26f154ef2e89352ad70a5415b8eDaniel Lehmann waitForAccess(mWriteAccessLatch); 7281f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro PhotoProcessor processor = new PhotoProcessor(b, mMaxDisplayPhotoDim, 7282f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxThumbnailPhotoDim); 7283f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7284f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Store the compressed photo in the photo store. 72855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore photoStore = ContactsContract.isProfileId(mRawContactId) 72865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ? mProfilePhotoStore 72875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro : mContactsPhotoStore; 72885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long photoFileId = photoStore.insert(processor); 7289f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7290c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro // Depending on whether we already had a data row to attach the photo 7291c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro // to, do an update or insert. 7292f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (mDataId != 0) { 7293f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Update the data record with the new photo. 7294f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues updateValues = new ContentValues(); 7295f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7296f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Signal that photo processing has already been handled. 7297f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 7298f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7299f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (photoFileId != 0) { 7300f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(Photo.PHOTO_FILE_ID, photoFileId); 7301f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7302f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(Photo.PHOTO, processor.getThumbnailPhotoBytes()); 7303c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro update(ContentUris.withAppendedId(Data.CONTENT_URI, mDataId), 7304c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro updateValues, null, null); 7305f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 7306f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Insert a new primary data record with the photo. 7307f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues insertValues = new ContentValues(); 7308f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7309f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Signal that photo processing has already been handled. 7310f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 7311f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7312f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 7313f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Data.IS_PRIMARY, 1); 7314f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (photoFileId != 0) { 7315f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Photo.PHOTO_FILE_ID, photoFileId); 7316f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7317f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Photo.PHOTO, processor.getThumbnailPhotoBytes()); 7318f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insert(RawContacts.CONTENT_URI.buildUpon() 7319f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .appendPath(String.valueOf(mRawContactId)) 7320f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .appendPath(RawContacts.Data.CONTENT_DIRECTORY).build(), 7321f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues); 7322f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7323c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro 7324f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7325c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro } catch (IOException e) { 7326c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro throw new RuntimeException(e); 7327f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7328c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro return null; 7329f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7330f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7331f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7332d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 7333d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7334d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 7335f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert * Returns an {@link AssetFileDescriptor} backed by the 7336d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 7337d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 7338f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 7339d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 7340d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 7341d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7342d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 7343d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7344f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 7345f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert ParcelFileDescriptor.fromData(byteData, CONTACT_MEMORY_FILE_NAME), 7346f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert byteData.length); 7347d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 7348ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert Log.w(TAG, "Problem writing stream into an ParcelFileDescriptor: " + e.toString()); 7349ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return null; 7350d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7351d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7352d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7353f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd) { 7354f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor(fd, AssetFileDescriptor.UNKNOWN_LENGTH); 7355f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 7356f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 7357f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd, long length) { 7358f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return fd != null ? new AssetFileDescriptor(fd, 0, length) : null; 7359f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 7360f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 7361d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 7362d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 7363d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 7364d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 7365d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 7366fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen private void outputRawContactsAsVCard(Uri uri, OutputStream stream, 7367fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen String selection, String[] selectionArgs) { 7368d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 7369dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen int vcardconfig = VCardConfig.VCARD_TYPE_DEFAULT; 7370fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if(uri.getBooleanQueryParameter( 7371fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, false)) { 7372dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen vcardconfig |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT; 7373dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen } 73747a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 7375dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen new VCardComposer(context, vcardconfig, false); 7376108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Writer writer = null; 73773711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen final Uri rawContactsUri; 73783711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen if (mapsToProfileDb(uri)) { 737982792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // Pre-authorize the URI, since the caller would have already gone through the 738082792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // permission check to get here, but the pre-authorization at the top level wouldn't 738182792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro // carry over to the raw contact. 738282792ae937085bfa1f7878166e89ca4ea84fd652Dave Santoro rawContactsUri = preAuthorizeUri(RawContactsEntity.PROFILE_CONTENT_URI); 73833711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen } else { 73843711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen rawContactsUri = RawContactsEntity.CONTENT_URI; 73853711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen } 7386108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 7387108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer = new BufferedWriter(new OutputStreamWriter(stream)); 73883711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen if (!composer.init(uri, selection, selectionArgs, null, rawContactsUri)) { 7389108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 7390108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return; 7391108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7392d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7393108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa while (!composer.isAfterLast()) { 7394108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.write(composer.createOneEntry()); 7395108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7396108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 7397108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.e(TAG, "IOException: " + e); 7398108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } finally { 7399108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa composer.terminate(); 7400108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa if (writer != null) { 7401108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 7402108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.close(); 7403108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 7404108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "IOException during closing output stream: " + e); 7405108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7406d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7407d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7408d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7409b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 74104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 74114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 7412415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 7413415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov waitForAccess(mReadAccessLatch); 7414415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 7415a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 74164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 7417b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 7418be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 74192d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 7420b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 7421b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 742224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 7423b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 7424f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 742542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 742624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 7427f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 7428f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov case CONTACTS_ID_PHOTO: 7429bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_PHOTO: 7430bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_PHOTO: 7431f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_ID_DISPLAY_PHOTO: 7432f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_DISPLAY_PHOTO: 7433f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_ID_DISPLAY_PHOTO: 7434f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case RAW_CONTACTS_ID_DISPLAY_PHOTO: 7435f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case DISPLAY_PHOTO: 7436f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return "image/jpeg"; 7437b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 743824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 7439be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 7440b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 744124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 7442b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 7443f481f22a9323fe338672f99b88b26c5f0725cd42David Brown case DATA: 744424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 7445f481f22a9323fe338672f99b88b26c5f0725cd42David Brown return Data.CONTENT_TYPE; 7446508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 74475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long id = ContentUris.parseId(uri); 74485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (ContactsContract.isProfileId(id)) { 74495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getDataMimeType(id); 74505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 74515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mContactsHelper.getDataMimeType(id); 74525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 745348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 745448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 745548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 745648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 74579005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 74589005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 745948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 746048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 746148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 746248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 746348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 746448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 746548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 746648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 7467b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 7468b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 7469b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 7470b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 7471b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 7472b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 7473b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 7474b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 7475c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 7476c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 7477c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 7478c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 7479d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES: 7480d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_TYPE; 7481d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID: 7482d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_ITEM_TYPE; 7483af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS: 7484af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.CONTENT_TYPE; 7485af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID: 7486af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.CONTENT_ITEM_TYPE; 7487af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID_PHOTOS: 7488af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.StreamItemPhotos.CONTENT_TYPE; 7489af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID_PHOTOS_ID: 7490af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.StreamItemPhotos.CONTENT_ITEM_TYPE; 7491af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_PHOTOS: 7492af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki throw new UnsupportedOperationException("Not supported for write-only URI " + uri); 749361efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 749461efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 74954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 74964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 74977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 749809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public String[] getDefaultProjection(Uri uri) { 749909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov final int match = sUriMatcher.match(uri); 750009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov switch (match) { 750109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS: 750209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP: 750309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_ID: 750409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP_ID: 750509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 750624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 750709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsProjectionMap.getColumnNames(); 750809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 75098727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov case CONTACTS_ID_ENTITIES: 751024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: 75118727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov return sEntityProjectionMap.getColumnNames(); 75128727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov 751309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_VCARD: 751409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_MULTI_VCARD: 751524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 751609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsVCardProjectionMap.getColumnNames(); 751709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 751809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS: 751909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS_ID: 752024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 752124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 752209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sRawContactsProjectionMap.getColumnNames(); 752309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 752409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DATA_ID: 752509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES: 752609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES_ID: 752709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS: 752809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS_ID: 752909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS: 753009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS_ID: 753124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 753209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDataProjectionMap.getColumnNames(); 753309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 753409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONE_LOOKUP: 753509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sPhoneLookupProjectionMap.getColumnNames(); 753609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 753709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 753809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 753909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sAggregationExceptionsProjectionMap.getColumnNames(); 754009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 754109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case SETTINGS: 754209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sSettingsProjectionMap.getColumnNames(); 754309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 754409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES: 754509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES_ID: 754609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDirectoryProjectionMap.getColumnNames(); 754709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 754809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov default: 754909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return null; 755009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 755109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 755209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 7553f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 7554f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7555f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 7556f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 7557f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7558f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7559f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 7560f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 7561f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 75625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().insertNameLookup(rawContactId, dataId, lookupType, name); 7563f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7564f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7565f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 7566f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 7567d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 7568f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7569f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7570f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 75712d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 7572d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 7573d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 7574d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 7575d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 7576d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 7577d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 7578d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 7579e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 7580916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 7581916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 7582e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 7583e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 75849a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov public boolean isPhoneNumber(String filter) { 75859a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean atLeastOneDigit = false; 75869a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov int len = filter.length(); 75879a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov for (int i = 0; i < len; i++) { 75889a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov char c = filter.charAt(i); 75899a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (c >= '0' && c <= '9') { 75909a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov atLeastOneDigit = true; 75919a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } else if (c != '*' && c != '#' && c != '+' && c != 'N' && c != '.' && c != ';' 75929a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov && c != '-' && c != '(' && c != ')' && c != ' ') { 75939a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 75949a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 75959a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 75969a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return atLeastOneDigit; 75979a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 75989a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 75994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 76007a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * Takes components of a name from the query parameters and returns a cursor with those 76017a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * components as well as all missing components. There is no database activity involved 76027a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * in this so the call can be made on the UI thread. 76037a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov */ 76047a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private Cursor completeName(Uri uri, String[] projection) { 76057a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (projection == null) { 76067a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov projection = sDataProjectionMap.getColumnNames(); 76077a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 76087a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 76097a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ContentValues values = new ContentValues(); 7610f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov DataRowHandlerForStructuredName handler = (DataRowHandlerForStructuredName) 7611f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov getDataRowHandler(StructuredName.CONTENT_ITEM_TYPE); 76127a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 76137a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov copyQueryParamsToContentValues(values, uri, 76147a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.DISPLAY_NAME, 76157a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PREFIX, 76167a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.GIVEN_NAME, 76177a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.MIDDLE_NAME, 76187a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.FAMILY_NAME, 76197a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.SUFFIX, 76207a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_NAME, 76217a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_FAMILY_NAME, 76227a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_MIDDLE_NAME, 76237a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_GIVEN_NAME 76247a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ); 76257a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 76267a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov handler.fixStructuredNameComponents(values, values); 76277a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 76287a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 76297a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov Object[] row = new Object[projection.length]; 76307a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (int i = 0; i < projection.length; i++) { 76317a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov row[i] = values.get(projection[i]); 76327a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 76337a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.addRow(row); 76347a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return cursor; 76357a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 76367a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 76377a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private void copyQueryParamsToContentValues(ContentValues values, Uri uri, String... columns) { 76387a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (String column : columns) { 76397a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String param = uri.getQueryParameter(column); 76407a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (param != null) { 76417a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov values.put(column, param); 76427a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 76437a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 76447a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 76457a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 76467a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 76477a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov /** 76484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 76494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 76504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 7651b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 7652b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 7653b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 7654b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 7655b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 76564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 76574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 7658b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 7659b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 7660b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 7661caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 76625e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 76635e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 76645e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 76655e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 76665e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 76675e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 76685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 76695e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 76705e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 76715e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 76725e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 7673caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 7674caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 7675caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 76765f1f4a062ac34d75d2dbf586702cbeb121cf09caDmitri Plotnikov Account[] accounts = accountManager.getAccountsByType(DEFAULT_ACCOUNT_TYPE); 7677caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 7678caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 7679caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 7680caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 76816f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 7682caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 76836f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 7684caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 7685f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 768673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 768743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Returns true if the specified account type and data set is writable. 768873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 768943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro protected boolean isWritableAccountWithDataSet(String accountTypeAndDataSet) { 769043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (accountTypeAndDataSet == null) { 7691bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 7692bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 7693bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 769443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Boolean writable = mAccountWritability.get(accountTypeAndDataSet); 769573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 769673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 769773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 769873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 7699627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 7700627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 770143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO(dsantoro): Need to update this logic to allow for sub-accounts. 7702627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 7703627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 770443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountTypeAndDataSet.equals(sync.accountType)) { 770573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 770673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 7707627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7708627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7709627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 7710627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 7711627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 771273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 771373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 771473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 771573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 771673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 771743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro mAccountWritability.put(accountTypeAndDataSet, writable); 771873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 7719627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7720b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 7721d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 7722f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 7723f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 7724f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7725f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 7726f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 7727f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 7728f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 7729f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7730f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7731f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 7732f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 7733f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 7734f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7735f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7736f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 7737f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7738f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 7739f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 7740f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7741f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7742f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 7743f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 7744f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 7745f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 7746f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 7747f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7748f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7749f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 7750f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 7751f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 7752f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 7753f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 7754f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 7755f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 7756f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7757f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7758f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 7759f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 7760f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7761f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 7762f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 7763f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 7764f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 7765f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 7766f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 77675fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 77685fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa 77695fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // Should match against the whole parameter instead of its suffix. 77705fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // e.g. The parameter "param" must not be found in "some_param=val". 77715fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (index > 0) { 77725fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa char prevChar = query.charAt(index - 1); 77735fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (prevChar != '?' && prevChar != '&') { 77745fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // With "some_param=val1¶m=val2", we should find second "param" occurrence. 77755fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa index += parameterLength; 77765fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa continue; 77775fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 7778f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7779f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7780f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 7781f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7782f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 7783f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 7784f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7785f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7786f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 7787f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 7788f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 7789f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7790f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7791f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7792f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 7793f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 7794f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 7795f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 7796f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 7797f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7798f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7799f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 7800f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 78015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 78020dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov protected boolean isAggregationUpgradeNeeded() { 78030dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 78040dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return false; 78050dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 78060dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 78075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int version = Integer.parseInt(mContactsHelper.getProperty( 78085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROPERTY_AGGREGATION_ALGORITHM, "1")); 78090dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return version < PROPERTY_AGGREGATION_ALGORITHM_VERSION; 78100dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 78110dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 7812bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void upgradeAggregationAlgorithmInBackground() { 78130dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // This upgrade will affect very few contacts, so it can be performed on the 78140dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // main thread during the initial boot after an OTA 78150dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 78160dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Upgrading aggregation algorithm"); 78170dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int count = 0; 78180dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 78195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = null; 78200dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 78215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 78225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db = mContactsHelper.getWritableDatabase(); 78235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 78245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.beginTransaction(); 78255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = db.query(true, 78260dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Tables.RAW_CONTACTS + " r1 JOIN " + Tables.RAW_CONTACTS + " r2", 78270dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov new String[]{"r1." + RawContacts._ID}, 78280dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov "r1." + RawContacts._ID + "!=r2." + RawContacts._ID + 78290dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.CONTACT_ID + "=r2." + RawContacts.CONTACT_ID + 78300dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_NAME + "=r2." + RawContacts.ACCOUNT_NAME + 783143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND r1." + RawContacts.ACCOUNT_TYPE + "=r2." + RawContacts.ACCOUNT_TYPE + 783243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND r1." + RawContacts.DATA_SET + "=r2." + RawContacts.DATA_SET, 78330dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov null, null, null, null, null); 78340dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 78350dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov while (cursor.moveToNext()) { 78360dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long rawContactId = cursor.getLong(0); 78370dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, 78380dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 78390dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov count++; 78400dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 78410dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 78420dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov cursor.close(); 78430dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 78445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator.aggregateInTransaction(mTransactionContext.get(), db); 7845bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 78465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.setTransactionSuccessful(); 78475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setProperty(PROPERTY_AGGREGATION_ALGORITHM, 78480dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov String.valueOf(PROPERTY_AGGREGATION_ALGORITHM_VERSION)); 78490dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 78505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (db != null) { 78515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.endTransaction(); 78525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 78530dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 78540dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Aggregation algorithm upgraded for " + count 78550dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov + " contacts, in " + (end - start) + "ms"); 78560dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 78570dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 78589a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 78599a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov /* Visible for testing */ 78609a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean isPhone() { 78619a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (!sIsPhoneInitialized) { 78629a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhone = new TelephonyManager(getContext()).isVoiceCapable(); 78639a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhoneInitialized = true; 78649a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 78659a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return sIsPhone; 78669a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 786746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 786846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private boolean handleDataUsageFeedback(Uri uri) { 786946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final long currentTimeMillis = System.currentTimeMillis(); 787046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String usageType = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 787146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] ids = uri.getLastPathSegment().trim().split(","); 787246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ArrayList<Long> dataIds = new ArrayList<Long>(); 787346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 787446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (String id : ids) { 787546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa dataIds.add(Long.valueOf(id)); 787646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 787746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final boolean successful; 787846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (TextUtils.isEmpty(usageType)) { 787946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.w(TAG, "Method for data usage feedback isn't specified. Ignoring."); 788046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = false; 788146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 788246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = updateDataUsageStat(dataIds, usageType, currentTimeMillis) > 0; 788346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 788446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 788546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Handle old API. This doesn't affect the result of this entire method. 788646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] questionMarks = new String[ids.length]; 788746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Arrays.fill(questionMarks, "?"); 788846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = Data._ID + " IN (" + TextUtils.join(",", questionMarks) + ")"; 78895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final Cursor cursor = mActiveDb.get().query( 7890ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA, 789146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { Data.CONTACT_ID }, 789246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa where, ids, null, null, null); 789346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 789446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa while (cursor.moveToNext()) { 789546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mSelectionArgs1[0] = cursor.getString(0); 789646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa ContentValues values2 = new ContentValues(); 789746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values2.put(Contacts.LAST_TIME_CONTACTED, currentTimeMillis); 78985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.CONTACTS, values2, Contacts._ID + "=?", 78995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mSelectionArgs1); 79005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 79015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 790246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 790346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 790446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 790546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 790646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 790746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return successful; 790846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 790946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 791046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 791146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Update {@link Tables#DATA_USAGE_STAT}. 791246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * 791346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @return the number of rows affected. 791446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 7915f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa @VisibleForTesting 7916f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa /* package */ int updateDataUsageStat( 7917f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa List<Long> dataIds, String type, long currentTimeMillis) { 791846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final int typeInt = sDataUsageTypeMap.get(type); 791946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = DataUsageStatColumns.DATA_ID + " =? AND " 792046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT + " =?"; 792146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] columns = 792246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { DataUsageStatColumns._ID, DataUsageStatColumns.TIMES_USED }; 792346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ContentValues values = new ContentValues(); 792446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (Long dataId : dataIds) { 792546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] args = new String[] { dataId.toString(), String.valueOf(typeInt) }; 79265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().beginTransaction(); 792746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 79285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final Cursor cursor = mActiveDb.get().query(Tables.DATA_USAGE_STAT, columns, where, 79295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro args, null, null, null); 793046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 793146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (cursor.getCount() > 0) { 793246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!cursor.moveToFirst()) { 793346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.e(TAG, 793446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa "moveToFirst() failed while getAccount() returned non-zero."); 793546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 793646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 793746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, cursor.getInt(1) + 1); 793846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 79395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.DATA_USAGE_STAT, values, 794046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns._ID + " =?", 794146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { cursor.getString(0) }); 794246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 794346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 794446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 794546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.DATA_ID, dataId); 794646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.USAGE_TYPE_INT, typeInt); 794746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, 1); 794846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 79495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().insert(Tables.DATA_USAGE_STAT, null, values); 795046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 79515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().setTransactionSuccessful(); 795246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 795346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 795446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 795546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 79565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().endTransaction(); 795746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 795846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 795946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 796046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return dataIds.size(); 796146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 796246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 796346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 796446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Returns a sort order String for promoting data rows (email addresses, phone numbers, etc.) 796546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * associated with a primary account. The primary account should be supplied from applications 796646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * with {@link ContactsContract#PRIMARY_ACCOUNT_NAME} and 796746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * {@link ContactsContract#PRIMARY_ACCOUNT_TYPE}. Null will be returned when the primary 796846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * account isn't available. 796946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 797046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private String getAccountPromotionSortOrder(Uri uri) { 797146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountName = 797246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_NAME); 797346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountType = 797446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_TYPE); 797546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 797646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Data rows associated with primary account should be promoted. 797746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountName)) { 797846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa StringBuilder sb = new StringBuilder(); 797946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append("(CASE WHEN " + RawContacts.ACCOUNT_NAME + "="); 798046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountName); 798146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountType)) { 798246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" AND " + RawContacts.ACCOUNT_TYPE + "="); 798346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountType); 798446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 798546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" THEN 0 ELSE 1 END)"); 798646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return sb.toString(); 798746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 798846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return null; 798946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 799046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 7991b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 7992b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 7993b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks the URI for a deferred snippeting request 7994b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if a deferred snippeting request is in the RI 7995b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 7996b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean deferredSnippetingRequested(Uri uri) { 7997b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson String deferredSnippeting = 7998b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson getQueryParameter(uri, SearchSnippetColumns.DEFERRED_SNIPPETING_KEY); 7999b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return !TextUtils.isEmpty(deferredSnippeting) && deferredSnippeting.equals("1"); 8000b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 8001b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 8002b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 8003b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks if query is a single word or not. 8004b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if the query is one word or not 8005b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 8006b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean isSingleWordQuery(String query) { 8007b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return query.split(QUERY_TOKENIZER_REGEX).length == 1; 8008b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 8009b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 8010b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 8011b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks the projection for a SNIPPET column indicating that a snippet is needed 8012b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if a snippet is needed or not. 8013b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 8014b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean snippetNeeded(String [] projection) { 8015b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return mDbHelper.get().isInProjection(projection, SearchSnippetColumns.SNIPPET); 8016b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 80174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 8018