ContactsProvider2.java revision 0e21a867a572679d64d79041eb574d13665178d4
14f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/* 24f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Copyright (C) 2009 The Android Open Source Project 34f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 44f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 54f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * you may not use this file except in compliance with the License. 64f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * You may obtain a copy of the License at 74f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 84f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 94f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * 104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Unless required by applicable law or agreed to in writing, software 114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * See the License for the specific language governing permissions and 144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * limitations under the License 154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts; 1828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar 19d9ec58265ae59a549880ef63cdfb5d0d977cdabaDmitri Plotnikovimport com.android.common.content.SQLiteContentProvider; 2053214b3ed12b0ff9cb589b6559311f2ac142f2e3Bjorn Bringertimport com.android.common.content.SyncStateContentProviderHelper; 215b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport com.android.providers.contacts.ContactAggregator.AggregationSuggestionParameter; 2297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 2324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoroimport com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns; 2497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 2597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 2697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 2797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 2897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 2997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 3071340347b4862d4b1368a5d69d1667e2245952e4Daisuke Miyakawaimport com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns; 3197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 322f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawaimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 3397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 3497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 3597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 3697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 371dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoroimport com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns; 3897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 3997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 4003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns; 4197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 4297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport com.android.providers.contacts.ContactsDatabaseHelper.StreamItemPhotosColumns; 44f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport com.android.providers.contacts.ContactsDatabaseHelper.StreamItemsColumns; 4597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 46ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmannimport com.android.providers.contacts.ContactsDatabaseHelper.Views; 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; 88f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoroimport android.database.sqlite.SQLiteConstraintException; 894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 9008ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwoodimport android.database.sqlite.SQLiteDoneException; 915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoroimport android.database.sqlite.SQLiteOpenHelper; 924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 93f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.graphics.Bitmap; 94f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.graphics.BitmapFactory; 954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 96d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.net.Uri.Builder; 97c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoroimport android.os.AsyncTask; 98bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Binder; 996ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 100bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Handler; 101bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.HandlerThread; 102bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Message; 103ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringertimport android.os.ParcelFileDescriptor; 104c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoroimport android.os.ParcelFileDescriptor.AutoCloseInputStream; 105bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Process; 106b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 10715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikovimport android.os.StrictMode; 1080dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikovimport android.os.SystemClock; 1090e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 1103d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 111508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 1123de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 113b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 11497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 11597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 11697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 11797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 1186d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Note; 11997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 12097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 12197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 1224928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.SipAddress; 12397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 12497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 125ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 1263de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 1275b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions; 1283de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 12971340347b4862d4b1368a5d69d1667e2245952e4Daisuke Miyakawaimport android.provider.ContactsContract.DataUsageFeedback; 130d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory; 131f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.provider.ContactsContract.DisplayPhoto; 1323de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 133bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.provider.ContactsContract.Intents; 1343de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 1351dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoroimport android.provider.ContactsContract.PhotoFiles; 1360c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoroimport android.provider.ContactsContract.Profile; 13709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 1383de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 1393711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenenimport android.provider.ContactsContract.RawContactsEntity; 140916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 1413de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 14282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 1433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport android.provider.ContactsContract.StreamItemPhotos; 144f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.provider.ContactsContract.StreamItems; 14597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.LiveFolders; 14697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.OpenableColumns; 14797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.SyncStateContract; 148a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 1499a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikovimport android.telephony.TelephonyManager; 150a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 151c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 153108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.BufferedWriter; 154d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 155f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport java.io.File; 156b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 157d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 158d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 159108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.OutputStreamWriter; 160108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.Writer; 16142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.text.SimpleDateFormat; 1627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 16346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawaimport java.util.Arrays; 1645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 16542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.util.Date; 166b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1670e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 169622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 170b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1710e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 172ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1785b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider 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 /** 206b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov * Property key for the legacy contact import version. The need for a version 2073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 2083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 2093d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 210b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final String PROPERTY_CONTACTS_IMPORTED = "contacts_imported_v1"; 211b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int PROPERTY_CONTACTS_IMPORT_VERSION = 1; 21251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final String PREF_LOCALE = "locale"; 2133d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2140dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final String PROPERTY_AGGREGATION_ALGORITHM = "aggregation_v2"; 2150dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final int PROPERTY_AGGREGATION_ALGORITHM_VERSION = 2; 2160dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 2170e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 2180e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 2195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final ProfileAwareUriMatcher sUriMatcher = 2205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ProfileAwareUriMatcher(UriMatcher.NO_MATCH); 2214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2222f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 2232f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * Used to insert a column into strequent results, which enables SQL to sort the list using 2242f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * the total times contacted. See also {@link #sStrequentFrequentProjectionMap}. 2252f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 2262f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private static final String TIMES_USED_SORT_COLUMN = "times_used_sort"; 2275e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 228d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 2292f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa + TIMES_USED_SORT_COLUMN + " DESC, " 2309b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 231d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 232d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 233d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 234d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 23545ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa private static final String FREQUENT_ORDER_BY = DataUsageStatColumns.TIMES_USED + " DESC," 23645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 23745ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa 2386e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 2399b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 2409b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 2419b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 2429b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 2436e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 2449b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 2459b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 2469b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 2479b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 248de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 249de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 2503716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Regex for splitting query strings - we split on any group of non-alphanumeric characters, 2513716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // excluding the @ symbol. 2523716f1447ceb21180d1301790eabd8b9453f486dDave Santoro /* package */ static final String QUERY_TOKENIZER_REGEX = "[^\\w@]+"; 2533716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 254d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 255d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 2565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 2575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 258a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_DATA = 1004; 2595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 2605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 2615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 2625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 263a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_PHOTO = 1009; 264bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_PHOTO = 1010; 265bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_PHOTO = 1011; 266bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_ID_DISPLAY_PHOTO = 1012; 267bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_DISPLAY_PHOTO = 1013; 268bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_DISPLAY_PHOTO = 1014; 269bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_AS_VCARD = 1015; 270bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_AS_MULTI_VCARD = 1016; 271bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_DATA = 1017; 272bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_DATA = 1018; 273bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_ID_ENTITIES = 1019; 274bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ENTITIES = 1020; 275bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_ENTITIES = 1021; 276bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_ID_STREAM_ITEMS = 1022; 277bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_STREAM_ITEMS = 1023; 278bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_STREAM_ITEMS = 1024; 279bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_FREQUENT = 1025; 2804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 2825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 2835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 28446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 285f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int RAW_CONTACTS_ID_DISPLAY_PHOTO = 2006; 286f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int RAW_CONTACTS_ID_STREAM_ITEMS = 2007; 28782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro private static final int RAW_CONTACTS_ID_STREAM_ITEMS_ID = 2008; 2884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2896bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2906bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 291ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 29248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 29348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 29448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 29548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 29648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 29748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 29848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 29948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 300a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3016bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 3026bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 303b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 304b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 305b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 30682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 30782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 3081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 30931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 31031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 311eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 312eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 313ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 314ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 315ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 316ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 318b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 3195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_SYNCSTATE = 11002; 3205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_SYNCSTATE_ID = 11003; 32135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 322c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 323c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 324c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 3261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 3271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 3281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 3291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 33046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 33146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 33209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 33309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 334d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES = 17001; 335d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES_ID = 17002; 336d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3377a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private static final int COMPLETE_NAME = 18000; 3387a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 33924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE = 19000; 34024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_ENTITIES = 19001; 34124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA = 19002; 34224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA_ID = 19003; 34324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_AS_VCARD = 19004; 34424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS = 19005; 34524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID = 19006; 34624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_DATA = 19007; 34724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_ENTITIES = 19008; 3485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_STATUS_UPDATES = 19009; 3493202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro private static final int PROFILE_RAW_CONTACT_ENTITIES = 19010; 35024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 35146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final int DATA_USAGE_FEEDBACK_ID = 20001; 35246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 3533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS = 21000; 3543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_PHOTOS = 21001; 3553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID = 21002; 3563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS = 21003; 3573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS_ID = 21004; 3583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_LIMIT = 21005; 3593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 360f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int DISPLAY_PHOTO = 22000; 361f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int PHOTO_DIMENSIONS = 22001; 362f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 3635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Inserts into URIs in this map will direct to the profile database if the parent record's 3645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // value (looked up from the ContentValues object with the key specified by the value in this 3655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // map) is in the profile ID-space (see {@link ProfileDatabaseHelper#PROFILE_ID_SPACE}). 3665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final Map<Integer, String> INSERT_URI_ID_VALUE_MAP = Maps.newHashMap(); 3675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro static { 3685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(DATA, Data.RAW_CONTACT_ID); 3695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(RAW_CONTACTS_DATA, Data.RAW_CONTACT_ID); 3705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STATUS_UPDATES, StatusUpdates.DATA_ID); 3715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS, StreamItems.RAW_CONTACT_ID); 3725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(RAW_CONTACTS_ID_STREAM_ITEMS, StreamItems.RAW_CONTACT_ID); 3735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID); 3745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS_ID_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID); 3755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 3765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 377dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID = 378dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 379dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME 380dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 381dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE 38243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + "=" + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND (" 38343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET 38443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + "=" + RawContactsColumns.CONCRETE_DATA_SET + " OR " 38543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 38643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL)" 387dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + " != 0"; 388dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 389dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID = 390dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 391dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 392dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 393dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 39443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND (" 39543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + "=" 39643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " OR " 39743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 39843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL)" 39943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + " AND " + Groups.AUTO_ADD + " != 0"; 400dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 401dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String[] PROJECTION_GROUP_ID 402dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana = new String[]{Tables.GROUPS + "." + Groups._ID}; 403dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 404dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_GROUPMEMBERSHIP_DATA = DataColumns.MIMETYPE_ID + "=? " 405dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.GROUP_ROW_ID + "=? " 406dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.RAW_CONTACT_ID + "=?"; 407dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 408dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_STARRED_FROM_RAW_CONTACTS = 409dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT " + RawContacts.STARRED 410dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?"; 411dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 412d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 413f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 414f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 415f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 41667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 41767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 4186cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 4196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro RawContactsColumns.CONCRETE_ACCOUNT_TYPE, 4206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro RawContactsColumns.CONCRETE_ACCOUNT_NAME, 42143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContactsColumns.CONCRETE_DATA_SET, 4223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 423f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 424ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 425ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 426d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 4276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro public static final int ACCOUNT_TYPE = 1; 4286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro public static final int ACCOUNT_NAME = 2; 42943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int DATA_SET = 3; 43043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int DATA_ID = 4; 43143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int CONTACT_ID = 5; 432ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 434f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov interface RawContactsQuery { 43519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 43619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 43719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 438ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 439ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 440ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 44143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.DATA_SET, 44219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 44319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 44419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 445ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 446ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 44743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int DATA_SET = 3; 44819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 44919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 450c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 451caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 45271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 45371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 45471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 45571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 45671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 45771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 45871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 45971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 4607cf50494501938f175d288077145acf49da8f171Daniel Lehmann + " WHERE " + DataColumns.MIMETYPE_ID + "=?" 4617cf50494501938f175d288077145acf49da8f171Daniel Lehmann + " AND " + GroupMembership.GROUP_ROW_ID + "=" 46271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 46371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 46471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 46571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 466a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 467a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 468a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 469a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 470a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 471a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 472a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 473a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 474a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 475a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 476a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 477a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 478c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Current contacts - those contacted within the last 3 days (in seconds) 479c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_CURRENT = 3 * 24 * 60 * 60; 480c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 481c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Recent contacts - those contacted within the last 30 days (in seconds) 482c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_RECENT = 30 * 24 * 60 * 60; 483c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 484f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa private static final String TIME_SINCE_LAST_USED = 485f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa "(strftime('%s', 'now') - " + DataUsageStatColumns.LAST_TIME_USED + "/1000)"; 486f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa 487c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov /* 488c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * Sorting order for email address suggestions: first starred, then the rest. 4892262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * second in_visible_group, then the rest. 4902262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * Within the four (starred/unstarred, in_visible_group/not-in_visible_group) groups 4912262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * - three buckets: very recently contacted, then fairly 492c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * recently contacted, then the rest. Within each of the bucket - descending count 49346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * of times contacted (both for data row and for contact row). If all else fails, alphabetical. 49446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * (Super)primary email address is returned before other addresses for the same contact. 495c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov */ 496c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final String EMAIL_FILTER_SORT_ORDER = 4972262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa Contacts.STARRED + " DESC, " 4982262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa + Contacts.IN_VISIBLE_GROUP + " DESC, " 499f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa + "(CASE WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_CURRENT 50046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 0 " 501f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa + " WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_RECENT 50246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 1 " 50346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " ELSE 2 END), " 50446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.TIMES_USED + " DESC, " 50546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Contacts.DISPLAY_NAME + ", " 50646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Data.CONTACT_ID + ", " 507c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_SUPER_PRIMARY + " DESC, " 508c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_PRIMARY + " DESC"; 50946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 51046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** Currently same as {@link #EMAIL_FILTER_SORT_ORDER} */ 51146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final String PHONE_FILTER_SORT_ORDER = EMAIL_FILTER_SORT_ORDER; 512c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 513916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 514916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 515916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 516916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 51792ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov NameLookupType.NICKNAME; 518916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 519f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov /** 520f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * If any of these columns are used in a Data projection, there is no point in 521f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * using the DISTINCT keyword, which can negatively affect performance. 522f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov */ 523f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov private static final String[] DISTINCT_DATA_PROHIBITING_COLUMNS = { 524f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data._ID, 525f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.RAW_CONTACT_ID, 526f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.NAME_RAW_CONTACT_ID, 527f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 528f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 52943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.DATA_SET, 53043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 531f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.DIRTY, 532f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.NAME_VERIFIED, 533f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SOURCE_ID, 534f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.VERSION, 535f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov }; 536916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 537f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsColumns = ProjectionMap.builder() 538f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CUSTOM_RINGTONE) 539f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME) 540f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_ALTERNATIVE) 541f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_SOURCE) 542f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.IN_VISIBLE_GROUP) 543f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LAST_TIME_CONTACTED) 544f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LOOKUP_KEY) 545f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME) 546f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME_STYLE) 547f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHOTO_ID) 548f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .add(Contacts.PHOTO_FILE_ID) 5493d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_URI) 5503d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_THUMBNAIL_URI) 551f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SEND_TO_VOICEMAIL) 552f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_ALTERNATIVE) 553f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_PRIMARY) 554f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.STARRED) 555f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.TIMES_CONTACTED) 556cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 557f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 558f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 559f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsPresenceColumns = ProjectionMap.builder() 560f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 561f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE) 562f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 563f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 564f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 565f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 566f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 567f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 568f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 569f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 570f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 571f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 572f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 573f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 574f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 575f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 576f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSnippetColumns = ProjectionMap.builder() 57703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov .add(SearchSnippetColumns.SNIPPET) 578f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 579f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 580f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactColumns = ProjectionMap.builder() 581f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_NAME) 582f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_TYPE) 58343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(RawContacts.DATA_SET) 58443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(RawContacts.ACCOUNT_TYPE_AND_DATA_SET) 585f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DIRTY) 586f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.NAME_VERIFIED) 587f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SOURCE_ID) 588f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.VERSION) 589f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 590f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 591f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactSyncColumns = ProjectionMap.builder() 592f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC1) 593f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC2) 594f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC3) 595f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC4) 596f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 597f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 598f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataColumns = ProjectionMap.builder() 599f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA1) 600f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA2) 601f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA3) 602f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA4) 603f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA5) 604f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA6) 605f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA7) 606f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA8) 607f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA9) 608f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA10) 609f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA11) 610f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA12) 611f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA13) 612f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA14) 613f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA15) 614f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA_VERSION) 615f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_PRIMARY) 616f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_SUPER_PRIMARY) 617f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.MIMETYPE) 618f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RES_PACKAGE) 619f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC1) 620f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC2) 621f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC3) 622f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC4) 623f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(GroupMembership.GROUP_SOURCE_ID) 624f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 625f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 626f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactPresenceColumns = ProjectionMap.builder() 627f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 628f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.PRESENCE) 629f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 630f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.CHAT_CAPABILITY) 631f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 632f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 633f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 634f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 635f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 636f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 637f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 638f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 639f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 640f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 641f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 642f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 643f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataPresenceColumns = ProjectionMap.builder() 644f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.PRESENCE, Tables.PRESENCE + "." + StatusUpdates.PRESENCE) 645f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CHAT_CAPABILITY, Tables.PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 646f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS, StatusUpdatesColumns.CONCRETE_STATUS) 647f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_TIMESTAMP, StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 648f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_RES_PACKAGE, StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 649f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_LABEL, StatusUpdatesColumns.CONCRETE_STATUS_LABEL) 650f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_ICON, StatusUpdatesColumns.CONCRETE_STATUS_ICON) 651f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 652f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 653038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 654f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sCountProjectionMap = ProjectionMap.builder() 655f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(BaseColumns._COUNT, "COUNT(*)") 656f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 657f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 658e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 659f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionMap = ProjectionMap.builder() 660f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts._ID) 661f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 662f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.NAME_RAW_CONTACT_ID) 66324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 664f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 665f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsPresenceColumns) 666f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 667f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 668916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 669f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionWithSnippetMap = ProjectionMap.builder() 670f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 671f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sSnippetColumns) 672f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 673916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6745e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 675f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentStarredProjectionMap = ProjectionMap.builder() 676f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 6772f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 678f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 679f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 680f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder() 681f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 6822f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, "SUM(" + DataUsageStatColumns.CONCRETE_TIMES_USED + ")") 683f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 684f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6854928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa /** 6864928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Used for Strequent Uri with {@link ContactsContract#STREQUENT_PHONE_ONLY}, which allows 6874928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * users to obtain part of Data columns. Right now Starred part just returns NULL for 6884928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * those data columns (frequent part should return real ones in data table). 6894928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa **/ 6904928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa private static final ProjectionMap sStrequentPhoneOnlyStarredProjectionMap 6914928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa = ProjectionMap.builder() 6924928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .addAll(sContactsProjectionMap) 6934928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 6944928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.NUMBER, "NULL") 6954928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.TYPE, "NULL") 6964928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.LABEL, "NULL") 6974928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .build(); 6984928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 6994928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa /** 7004928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Used for Strequent Uri with {@link ContactsContract#STREQUENT_PHONE_ONLY}, which allows 7014928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * users to obtain part of Data columns. We hard-code {@link Contacts#IS_USER_PROFILE} to NULL, 7024928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * because sContactsProjectionMap specifies a field that doesn't exist in the view behind the 7034928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * query that uses this projection map. 7044928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa **/ 7054928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa private static final ProjectionMap sStrequentPhoneOnlyFrequentProjectionMap 7064928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa = ProjectionMap.builder() 7074928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .addAll(sContactsProjectionMap) 7084928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, DataUsageStatColumns.CONCRETE_TIMES_USED) 7094928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.NUMBER) 7104928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.TYPE) 7114928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.LABEL) 7124928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Contacts.IS_USER_PROFILE, "NULL") 7134928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .build(); 7144928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 715f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 716f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsVCardProjectionMap = ProjectionMap.builder() 717fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen .add(Contacts._ID) 718f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME + " || '.vcf'") 719f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.SIZE, "NULL") 720f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 721f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 722ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 723f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactsProjectionMap = ProjectionMap.builder() 724f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 725f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 726f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 727f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_PRIMARY) 728f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_ALTERNATIVE) 729f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_SOURCE) 730f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME) 731f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME_STYLE) 732f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_PRIMARY) 733f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_ALTERNATIVE) 734f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.TIMES_CONTACTED) 735f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.LAST_TIME_CONTACTED) 736f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CUSTOM_RINGTONE) 737f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SEND_TO_VOICEMAIL) 738f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 739f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.AGGREGATION_MODE) 74024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 741f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 742f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 743f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 744f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 745a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the raw entity view*/ 746f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawEntityProjectionMap = ProjectionMap.builder() 747f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 748f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 749f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.Entity.DATA_ID) 750f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 751f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 75224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 753f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 754f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 755f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 756f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 757f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 758a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the contact entity view*/ 759f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sEntityProjectionMap = ProjectionMap.builder() 760f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity._ID) 761f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.CONTACT_ID) 762f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.RAW_CONTACT_ID) 763f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DATA_ID) 764f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.NAME_RAW_CONTACT_ID) 765f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DELETED) 76624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 767f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 768f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 769f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 770f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 771f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 772f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 773f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 774f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 776f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataProjectionMap = ProjectionMap.builder() 777f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID) 778f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RAW_CONTACT_ID) 779f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CONTACT_ID) 780f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.NAME_RAW_CONTACT_ID) 78124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 782f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 783f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 784f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 785f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 786f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 787f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 788f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 790f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDistinctDataProjectionMap = ProjectionMap.builder() 791f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID, "MIN(" + Data._ID + ")") 792f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 79324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 794f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 795f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 796f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 797f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 798f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 799f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 8009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 801f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sPhoneLookupProjectionMap = ProjectionMap.builder() 802f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup._ID, "contacts_view." + Contacts._ID) 803f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LOOKUP_KEY, "contacts_view." + Contacts.LOOKUP_KEY) 804f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.DISPLAY_NAME, "contacts_view." + Contacts.DISPLAY_NAME) 805f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LAST_TIME_CONTACTED, "contacts_view." + Contacts.LAST_TIME_CONTACTED) 806f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TIMES_CONTACTED, "contacts_view." + Contacts.TIMES_CONTACTED) 807f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.STARRED, "contacts_view." + Contacts.STARRED) 808f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.IN_VISIBLE_GROUP, "contacts_view." + Contacts.IN_VISIBLE_GROUP) 809f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.PHOTO_ID, "contacts_view." + Contacts.PHOTO_ID) 8103d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_URI, "contacts_view." + Contacts.PHOTO_URI) 8113d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_THUMBNAIL_URI, "contacts_view." + Contacts.PHOTO_THUMBNAIL_URI) 812f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.CUSTOM_RINGTONE, "contacts_view." + Contacts.CUSTOM_RINGTONE) 813f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.HAS_PHONE_NUMBER, "contacts_view." + Contacts.HAS_PHONE_NUMBER) 814f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.SEND_TO_VOICEMAIL, "contacts_view." + Contacts.SEND_TO_VOICEMAIL) 815f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.NUMBER, Phone.NUMBER) 816f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TYPE, Phone.TYPE) 817f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LABEL, Phone.LABEL) 8182530512f639c4979fd7371c7dd25dd67e8118124Bai Tao .add(PhoneLookup.NORMALIZED_NUMBER, Phone.NORMALIZED_NUMBER) 819f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 820f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 821ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 822f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsProjectionMap = ProjectionMap.builder() 823f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups._ID) 824f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_NAME) 825f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_TYPE) 82643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(Groups.DATA_SET) 82743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(Groups.ACCOUNT_TYPE_AND_DATA_SET) 828f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SOURCE_ID) 829f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DIRTY) 830f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.VERSION) 831f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.RES_PACKAGE) 832f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE) 833f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE_RES) 834f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.GROUP_VISIBLE) 835f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYSTEM_ID) 836f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DELETED) 837f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.NOTES) 838f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SHOULD_SYNC) 839f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.FAVORITES) 840f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.AUTO_ADD) 841c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov .add(Groups.GROUP_IS_READ_ONLY) 842f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC1) 843f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC2) 844f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC3) 845f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC4) 846f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 847f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 848ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 849f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsSummaryProjectionMap = ProjectionMap.builder() 850f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sGroupsProjectionMap) 851f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_COUNT, 852f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(" + ContactsColumns.CONCRETE_ID + ") FROM " 853f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Tables.CONTACTS_JOIN_RAW_CONTACTS_DATA_FILTERED_BY_GROUPMEMBERSHIP 854f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")") 855f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_WITH_PHONES, 856f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(" + ContactsColumns.CONCRETE_ID + ") FROM " 857f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Tables.CONTACTS_JOIN_RAW_CONTACTS_DATA_FILTERED_BY_GROUPMEMBERSHIP 858f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " WHERE " + Contacts.HAS_PHONE_NUMBER + ")") 859f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .build(); 860f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa 861f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa // This is only exposed as hidden API for the contacts app, so we can be very specific in 862f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa // the filtering 863f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa private static final ProjectionMap sGroupsSummaryProjectionMapWithGroupCountPerAccount = 864f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa ProjectionMap.builder() 865f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .addAll(sGroupsSummaryProjectionMap) 866f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .add(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT, 867f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(*) FROM " + Views.GROUPS + " WHERE " 868f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + "(" + Groups.ACCOUNT_NAME + "=" 869f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + GroupsColumns.CONCRETE_ACCOUNT_NAME 870f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " AND " 871f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.ACCOUNT_TYPE + "=" + GroupsColumns.CONCRETE_ACCOUNT_TYPE 872f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " AND " 873f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.DELETED + "=0 AND " 874f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.FAVORITES + "=0 AND " 875f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.AUTO_ADD + "=0" 876f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")" 877f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " GROUP BY " 878f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.ACCOUNT_NAME + ", " + Groups.ACCOUNT_TYPE 879f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")") 880f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 881f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 882373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 883f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sAggregationExceptionsProjectionMap = ProjectionMap.builder() 884f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id") 885f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.TYPE) 886f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID1) 887f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID2) 888f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 889f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 890eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 891f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSettingsProjectionMap = ProjectionMap.builder() 892f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_NAME) 893f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_TYPE) 894f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro .add(Settings.DATA_SET) 895f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_VISIBLE) 896f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.SHOULD_SYNC) 897f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ANY_UNSYNCED, 898f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 899f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ",(SELECT " 900f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "(CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL" 901f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 902f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE MIN(" + Groups.SHOULD_SYNC + ")" 903f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)" 904f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.GROUPS 905f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 906f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_NAME 907f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 908f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_ACCOUNT_TYPE 909f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + " AND ((" + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 910f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_DATA_SET + " IS NULL) OR (" 911f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + GroupsColumns.CONCRETE_DATA_SET + "=" 912f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_DATA_SET + "))))=0" 913f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 914f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE 0" 915f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)") 916f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_COUNT, 917f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 918f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 919f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 920f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 921f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 922f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 923f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_WITH_PHONES, 924f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 925f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 926f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 927f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Contacts.HAS_PHONE_NUMBER 928f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 929f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 930f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 931f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 932f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 93382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 934f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStatusUpdatesProjectionMap = ProjectionMap.builder() 935f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PresenceColumns.RAW_CONTACT_ID) 936f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.DATA_ID, DataColumns.CONCRETE_ID) 937f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_ACCOUNT) 938f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_HANDLE) 939f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PROTOCOL) 940f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 941f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // properly enforce uniqueness of null values 942f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CUSTOM_PROTOCOL, 943f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL + "=''" 944f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN NULL" 945f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END)") 946f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PRESENCE) 947f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CHAT_CAPABILITY) 948f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS) 949f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_TIMESTAMP) 950f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_RES_PACKAGE) 951f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_ICON) 952f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_LABEL) 953f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 954f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 9553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Contains StreamItems columns */ 9563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemsProjectionMap = ProjectionMap.builder() 9579b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems._ID) 9589b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.CONTACT_ID) 959af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann .add(StreamItems.CONTACT_LOOKUP_KEY) 9609b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.ACCOUNT_NAME) 9619b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.ACCOUNT_TYPE) 9629b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.DATA_SET) 9633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 9649b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.RAW_CONTACT_SOURCE_ID) 9653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_PACKAGE) 9663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_ICON) 9673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_LABEL) 9683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TEXT) 9693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TIMESTAMP) 9703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.COMMENTS) 9710bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC1) 9720bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC2) 9730bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC3) 9740bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC4) 9753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 9763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 9773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemPhotosProjectionMap = ProjectionMap.builder() 9783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos._ID, StreamItemPhotosColumns.CONCRETE_ID) 9793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 9800bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.RAW_CONTACT_SOURCE_ID, RawContactsColumns.CONCRETE_SOURCE_ID) 9813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.STREAM_ITEM_ID) 9823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.SORT_INDEX) 9836802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .add(StreamItemPhotos.PHOTO_FILE_ID) 9846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .add(StreamItemPhotos.PHOTO_URI, 9856802030a777c0c3ba1dc029c534cca4784260632Dave Santoro "'" + DisplayPhoto.CONTENT_URI + "'||'/'||" + StreamItemPhotos.PHOTO_FILE_ID) 9861dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.HEIGHT) 9871dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.WIDTH) 9881dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.FILESIZE) 9890bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC1) 9900bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC2) 9910bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC3) 9920bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC4) 9933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 9943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 9951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 996f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sLiveFoldersProjectionMap = ProjectionMap.builder() 997f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders._ID, Contacts._ID) 998f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders.NAME, Contacts.DISPLAY_NAME) 999f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 1000f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // for contacts without a photo 1001f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // .add(LiveFolders.ICON_BITMAP, Photos.DATA) 1002f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 1003f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 1004d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** Contains {@link Directory} columns */ 1005f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDirectoryProjectionMap = ProjectionMap.builder() 1006f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory._ID) 1007f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.PACKAGE_NAME) 1008f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.TYPE_RESOURCE_ID) 1009f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DISPLAY_NAME) 1010f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DIRECTORY_AUTHORITY) 1011f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_TYPE) 1012f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_NAME) 1013f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.EXPORT_SUPPORT) 1014778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.SHORTCUT_SUPPORT) 1015778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.PHOTO_SUPPORT) 1016f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 10177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 10189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 10199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 10209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 10219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 10229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 10239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 10242526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 10252526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 1026bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1027bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 1028bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1029bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 103051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 103103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_START_MATCH = "["; 103203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_END_MATCH = "]"; 103303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_ELLIPSIS = "..."; 103403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final int DEFAULT_SNIPPET_ARG_MAX_TOKENS = -10; 103503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 10369a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhoneInitialized; 10379a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhone; 10389a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 1039f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 10401129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 10411129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 10422526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 10432526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 1044f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 1045f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 104646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 104746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Stores mapping from type Strings exposed via {@link DataUsageFeedback} to 104846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type integers in {@link DataUsageStatColumns}. 104946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 105046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final Map<String, Integer> sDataUsageTypeMap; 105146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 10524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 10534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 1054a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 1055d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 1056d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 1057a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA); 1058a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES); 10593653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 10603653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 10612d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 10622d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 1063a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO); 1064f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/display_photo", 1065f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_ID_DISPLAY_PHOTO); 10663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/stream_items", 10673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_ID_STREAM_ITEMS); 1068c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); 10695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 10705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 10712149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA); 1072bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/photo", 1073bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro CONTACTS_LOOKUP_PHOTO); 10745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 10752149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", 10762149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov CONTACTS_LOOKUP_ID_DATA); 1077bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/photo", 1078bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro CONTACTS_LOOKUP_ID_PHOTO); 1079f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/display_photo", 1080f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_LOOKUP_DISPLAY_PHOTO); 1081f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/display_photo", 1082f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_LOOKUP_ID_DISPLAY_PHOTO); 1083a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", 1084a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ENTITIES); 1085a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", 1086a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ID_ENTITIES); 10873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/stream_items", 10883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_STREAM_ITEMS); 10893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/stream_items", 10903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_ID_STREAM_ITEMS); 1091f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 109242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 109342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 10945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 1095ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 1096ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 10975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 109845ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "contacts/frequent", CONTACTS_FREQUENT); 10993653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 11005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 11015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 11025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 1103f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/display_photo", 1104f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro RAW_CONTACTS_ID_DISPLAY_PHOTO); 110546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 11063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items", 11073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann RAW_CONTACTS_ID_STREAM_ITEMS); 110882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items/#", 110982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro RAW_CONTACTS_ID_STREAM_ITEMS_ID); 111046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 111146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 1112b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 11134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 11144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 1115ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 111648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 11175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 1118ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 11194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 112048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 11211dac83b8fa58944acfd00f44e717a7dddc659d2dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup", EMAILS_LOOKUP); 11225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 11235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 11244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 1125ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 112648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 112746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** "*" is in CSV form with data ids ("123,456,789") */ 112846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "data/usagefeedback/*", DATA_USAGE_FEEDBACK_ID); 11291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1130ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 1131ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 1132ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 1133ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 113435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 1135b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 1136b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 11375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/" + SyncStateContentProviderHelper.PATH, 11385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_SYNCSTATE); 11395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, 11405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "profile/" + SyncStateContentProviderHelper.PATH + "/#", 11415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_SYNCSTATE_ID); 114235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1143a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 1144b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 1145b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 1146b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 1147b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 11484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1149eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 1150eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 115182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 115282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 11531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1154c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 1155c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 1156c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 1157c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 11582d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 1159c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 1160c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 11611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 11621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 11631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 11641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 11651b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 11661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 11671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 11681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 116909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 117009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 1171d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1172d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories", DIRECTORIES); 1173d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories/#", DIRECTORIES_ID); 11747a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 11757a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "complete_name", COMPLETE_NAME); 117624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 117724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile", PROFILE); 117824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/entities", PROFILE_ENTITIES); 117924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data", PROFILE_DATA); 118024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data/#", PROFILE_DATA_ID); 118124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/as_vcard", PROFILE_AS_VCARD); 118224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts", PROFILE_RAW_CONTACTS); 118324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#", 118424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID); 118524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/data", 118624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_DATA); 118724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/entity", 118824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_ENTITIES); 11895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/status_updates", 11905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_STATUS_UPDATES); 11913202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contact_entities", 11923202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro PROFILE_RAW_CONTACT_ENTITIES); 119346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 11943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items", STREAM_ITEMS); 11953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/photo", STREAM_ITEMS_PHOTOS); 11963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#", STREAM_ITEMS_ID); 11973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo", STREAM_ITEMS_ID_PHOTOS); 11983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo/#", 11993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann STREAM_ITEMS_ID_PHOTOS_ID); 12003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items_limit", STREAM_ITEMS_LIMIT); 12013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 12025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "display_photo/#", DISPLAY_PHOTO); 1203f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "photo_dimensions", PHOTO_DIMENSIONS); 1204f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 120546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa HashMap<String, Integer> tmpTypeMap = new HashMap<String, Integer>(); 120646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_CALL, DataUsageStatColumns.USAGE_TYPE_INT_CALL); 120746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_LONG_TEXT, 120846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT); 120946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_SHORT_TEXT, 121046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_SHORT_TEXT); 121146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sDataUsageTypeMap = Collections.unmodifiableMap(tmpTypeMap); 121219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 121319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 1214d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static class DirectoryInfo { 1215d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String authority; 1216d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountName; 1217d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountType; 1218d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 1219d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1220d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 1221d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Cached information about contact directories. 1222d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 12234458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private HashMap<String, DirectoryInfo> mDirectoryCache = new HashMap<String, DirectoryInfo>(); 12244458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private boolean mDirectoryCacheValid = false; 1225d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 12263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 122743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * An entry in group id cache. It maps the combination of (account type, account name, data set, 1228ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1229ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1230e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov public static class GroupIdCacheEntry { 1231ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1232ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 123343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet; 1234ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1235ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1236ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1237a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1238e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1239e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1240e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // is a list of groups with this group id. 1241e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1242e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov 124324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 1244f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Maximum dimension (height or width) of display photos. Larger images will be scaled 1245f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * to fit. 1246f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 1247f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private int mMaxDisplayPhotoDim; 1248f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1249f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 1250f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Maximum dimension (height or width) of photo thumbnails. 1251f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 1252f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private int mMaxThumbnailPhotoDim; 1253f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 12545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 12555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Sub-provider for handling profile requests against the profile database. 12565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 12575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ProfileProvider mProfileProvider; 1258f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 12594097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1260f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1261315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1262622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1263622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 126472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private ContactDirectoryManager mContactDirectoryManager; 12655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 12675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * The active (thread-local) database. This will be switched between a contacts-specific 12685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database and a profile-specific database, depending on what the current operation is 12695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * targeted to. 12705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 12715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<SQLiteDatabase> mActiveDb = new ThreadLocal<SQLiteDatabase>(); 12725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This variable keeps track of whether the current operation is intended for the profile DB. 12745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mInProfileMode = new ThreadLocal<Boolean>(); 12755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Whether we're currently in the process of applying a batch of operations. 12775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mApplyingBatch = new ThreadLocal<Boolean>(); 12785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Separate data row handler instances for contact data and profile data. 12805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private HashMap<String, DataRowHandler> mDataRowHandlers; 12815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private HashMap<String, DataRowHandler> mProfileDataRowHandlers; 12825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile, we will use one of two 12845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // database helper instances. 12855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<ContactsDatabaseHelper> mDbHelper = 12865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<ContactsDatabaseHelper>(); 12875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ContactsDatabaseHelper mContactsHelper; 12885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ProfileDatabaseHelper mProfileHelper; 12895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile or not, we will use one of 12915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // two aggregator instances. 12925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<ContactAggregator> mAggregator = new ThreadLocal<ContactAggregator>(); 1293622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 12945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ContactAggregator mProfileAggregator; 12955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile or not, we will use one of 12975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // two photo store instances (with their files stored in separate subdirectories). 12985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<PhotoStore> mPhotoStore = new ThreadLocal<PhotoStore>(); 12995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private PhotoStore mContactsPhotoStore; 13005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private PhotoStore mProfilePhotoStore; 13015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // The active transaction context will switch depending on the operation being performed. 13035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Both transaction contexts will be cleared out when a batch transaction is started, and 13045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // each will be processed separately when a batch transaction completes. 13055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private TransactionContext mContactTransactionContext = new TransactionContext(false); 13065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private TransactionContext mProfileTransactionContext = new TransactionContext(true); 13075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<TransactionContext> mTransactionContext = 13085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<TransactionContext>(); 13095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This database reference will only be referenced when a batch operation is in progress 13115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // that includes profile DB operations. It is used to create and handle a separate transaction 13125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // around that batch. Outside of such a batch operation, this will be null. 13135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<SQLiteDatabase> mProfileDbForBatch = 13145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<SQLiteDatabase>(); 13155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This flag is set during a batch operation that involves the profile DB to indicate that 13175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // errors occurred during processing of one of the profile operations. 13185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mProfileErrorsInBatch = new ThreadLocal<Boolean>(); 13195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1320f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1321a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1322d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1323f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private SearchIndexManager mSearchIndexManager; 1324a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 132520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 132673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 132720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 132809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 13293826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private boolean mProviderStatusUpdateNeeded; 133009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 133115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mReadAccessLatch; 133215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mWriteAccessLatch; 133315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private boolean mAccountUpdateListenerRegistered; 1334bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private boolean mOkToOpenAccess = true; 133573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 13361a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 13371a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 133881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 133981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 13404cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 13413826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private int mContactsAccountCount; 1342d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1343bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private HandlerThread mBackgroundThread; 1344bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private Handler mBackgroundHandler; 1345bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1346f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private long mLastPhotoCleanup = 0; 1347f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 13484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 13494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1350663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 1351663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "ContactsProvider2.onCreate start"); 1352663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 1353de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1354ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1355ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1356ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1357ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1358ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1359663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } finally { 1360663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 1361663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "ContactsProvider2.onCreate finish"); 1362663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 1363ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1364ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 136535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1366ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 136715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov StrictMode.setThreadPolicy( 136815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); 136915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 13703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Resources resources = getContext().getResources(); 1371f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxDisplayPhotoDim = resources.getInteger( 1372f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro R.integer.config_max_display_photo_dim); 1373f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxThumbnailPhotoDim = resources.getInteger( 1374f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro R.integer.config_max_thumbnail_photo_dim); 13753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 13765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper = (ContactsDatabaseHelper) getDatabaseHelper(); 13775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mContactsHelper); 137872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager = new ContactDirectoryManager(this); 1379a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 138065ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 1381bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // The provider is closed for business until fully initialized 138215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = new CountDownLatch(1); 138315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = new CountDownLatch(1); 138472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1385bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread = new HandlerThread("ContactsProviderWorker", 1386bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Process.THREAD_PRIORITY_BACKGROUND); 1387bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread.start(); 1388bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { 1389bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 1390bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void handleMessage(Message msg) { 1391bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov performBackgroundTask(msg.what, msg.obj); 1392bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1393bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov }; 13942a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 13955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Set up the sub-provider for handling profiles. 13965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileProvider = getProfileProvider(); 13975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ProviderInfo profileInfo = new ProviderInfo(); 13985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileInfo.readPermission = "android.permission.READ_PROFILE"; 13995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileInfo.writePermission = "android.permission.WRITE_PROFILE"; 14005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileProvider.attachInfo(getContext(), profileInfo); 14015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper = (ProfileDatabaseHelper) mProfileProvider.getDatabaseHelper(); 14025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 140315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_INITIALIZE); 1404bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1405bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 1406bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_LOCALE); 1407bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM); 140805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_SEARCH_INDEX); 1409bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_PROVIDER_STATUS); 141015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_OPEN_WRITE_ACCESS); 1411f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 14123826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 141349d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov return true; 14144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 14154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1416767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 141751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 141851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 141904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 142015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 14215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mLegacyApiSupport = new LegacyApiSupport(context, mContactsHelper, this, 14225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mGlobalSearchSupport); 14234cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 14245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mNameSplitter = mContactsHelper.createNameSplitter(); 14254cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 14264cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 14275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mCommonNicknameCache = new CommonNicknameCache(mContactsHelper.getReadableDatabase()); 1428cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 14295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator = new ContactAggregator(this, mContactsHelper, 143015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 14315b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 14325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator = new ProfileAggregator(this, mProfileHelper, 14335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 14345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1435f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSearchIndexManager = new SearchIndexManager(this); 14365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 14375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore = new PhotoStore(getContext().getFilesDir(), mContactsHelper); 14385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore = new PhotoStore(new File(getContext().getFilesDir(), "profile"), 14395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper); 14405b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 1441bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 14425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro initDataRowHandlers(mDataRowHandlers, mContactsHelper, mContactAggregator, 14435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore); 14445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDataRowHandlers = new HashMap<String, DataRowHandler>(); 14455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro initDataRowHandlers(mProfileDataRowHandlers, mProfileHelper, mProfileAggregator, 14465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore); 14475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 14485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Set initial thread-local state variables for the Contacts DB. 14495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 14505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 1451bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 14525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void initDataRowHandlers(Map<String, DataRowHandler> handlerMap, 14535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ContactsDatabaseHelper dbHelper, ContactAggregator contactAggregator, 14545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore photoStore) { 14555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Context context = getContext(); 14565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Email.CONTENT_ITEM_TYPE, 14575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForEmail(context, dbHelper, contactAggregator)); 14585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Im.CONTENT_ITEM_TYPE, 14595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForIm(context, dbHelper, contactAggregator)); 14605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Organization.CONTENT_ITEM_TYPE, 14615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForOrganization(context, dbHelper, contactAggregator)); 14625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Phone.CONTENT_ITEM_TYPE, 14635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForPhoneNumber(context, dbHelper, contactAggregator)); 14645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Nickname.CONTENT_ITEM_TYPE, 14655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForNickname(context, dbHelper, contactAggregator)); 14665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(StructuredName.CONTENT_ITEM_TYPE, 14675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForStructuredName(context, dbHelper, contactAggregator, 1468bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mNameSplitter, mNameLookupBuilder)); 14695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(StructuredPostal.CONTENT_ITEM_TYPE, 14705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForStructuredPostal(context, dbHelper, contactAggregator, 1471bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mPostalSplitter)); 14725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(GroupMembership.CONTENT_ITEM_TYPE, 14735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForGroupMembership(context, dbHelper, contactAggregator, 1474bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mGroupIdCache)); 14755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Photo.CONTENT_ITEM_TYPE, 14765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForPhoto(context, dbHelper, contactAggregator, photoStore)); 14775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Note.CONTENT_ITEM_TYPE, 14785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForNote(context, dbHelper, contactAggregator)); 1479bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1480bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1481bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /** 1482bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Visible for testing. 1483bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov */ 1484bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 1485bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return new PhotoPriorityResolver(context); 1486bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1487bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1488bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task) { 1489bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendEmptyMessage(task); 1490bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1491bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1492bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task, Object arg) { 1493bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(task, arg)); 1494bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1495bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1496bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void performBackgroundTask(int task, Object arg) { 1497bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov switch (task) { 149815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_INITIALIZE: { 149915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov initForDefaultLocale(); 150015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch.countDown(); 150115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = null; 150215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov break; 150315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 150415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 150515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_OPEN_WRITE_ACCESS: { 1506bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (mOkToOpenAccess) { 150715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch.countDown(); 150815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = null; 1509bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1510bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1511bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1512bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1513bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS: { 1514bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1515bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov importLegacyContactsInBackground(); 1516bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1517bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1518bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1519bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1520bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_ACCOUNTS: { 152115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 152215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (!mAccountUpdateListenerRegistered) { 152315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov AccountManager.get(context).addOnAccountsUpdatedListener(this, null, false); 152415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mAccountUpdateListenerRegistered = true; 152515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 152615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 15275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Update the accounts for both the contacts and profile DBs. 152815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Account[] accounts = AccountManager.get(context).getAccounts(); 15295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 1530bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean accountsChanged = updateAccountsInBackground(accounts); 15315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 15325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro accountsChanged |= updateAccountsInBackground(accounts); 15335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1534bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateContactsAccountCount(accounts); 1535bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateDirectoriesInBackground(accountsChanged); 1536bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1537bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1538bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1539bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_LOCALE: { 1540bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateLocaleInBackground(); 1541bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1542bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1543bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1544fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov case BACKGROUND_TASK_CHANGE_LOCALE: { 1545fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov changeLocaleInBackground(); 1546fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov break; 1547fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1548fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1549bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM: { 1550bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isAggregationUpgradeNeeded()) { 1551bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov upgradeAggregationAlgorithmInBackground(); 1552bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1553bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1554bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1555bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 155605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_SEARCH_INDEX: { 155705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov updateSearchIndexInBackground(); 155805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov break; 155905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 156005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1561bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_PROVIDER_STATUS: { 1562bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateProviderStatus(); 1563bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1564bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1565bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1566bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_DIRECTORIES: { 1567bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (arg != null) { 1568bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.onPackageChanged((String) arg); 1569bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1570bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1571bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1572f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1573f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case BACKGROUND_TASK_CLEANUP_PHOTOS: { 1574f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Check rate limit. 1575f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long now = System.currentTimeMillis(); 1576f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (now - mLastPhotoCleanup > PHOTO_CLEANUP_RATE_LIMIT) { 1577f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mLastPhotoCleanup = now; 15785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 15795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Clean up photo stores for both contacts and profiles. 15805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 15815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cleanupPhotoStore(); 15825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 1583f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro cleanupPhotoStore(); 1584f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro break; 1585f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1586f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1587bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 15884cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 15894cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 159053fac8f99f3884c372c907a76766d27fa9e1d95fDmitri Plotnikov public void onLocaleChanged() { 15913826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 15923826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 15934f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov return; 15944f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov } 15954f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 1596fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_CHANGE_LOCALE); 15974cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 159851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 159951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 160051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 160151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 160251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 160351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 160451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 160551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 1606bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateLocaleInBackground() { 1607f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 1608f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 1609f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 1610f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 1611f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 1612f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 161351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 161451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 161551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 161651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 161751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 161851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 161951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 162051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 162151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 16225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setLocale(this, currentLocale); 16235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper.setLocale(this, currentLocale); 1624bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).apply(); 1625bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov setProviderStatus(providerStatus); 1626bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 162751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1628fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov /** 1629fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov * Reinitializes the provider for a new locale. 1630fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov */ 1631fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private void changeLocaleInBackground() { 1632fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Re-initializing the provider without stopping it. 1633fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Locking the database will prevent inserts/updates/deletes from 1634fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // running at the same time, but queries may still be running 1635fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // on other threads. Those queries may return inconsistent results. 16365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mContactsHelper.getWritableDatabase(); 16375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase profileDb = mProfileHelper.getWritableDatabase(); 1638fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.beginTransaction(); 16395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.beginTransaction(); 1640fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov try { 1641fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov initForDefaultLocale(); 1642fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.setTransactionSuccessful(); 16435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.setTransactionSuccessful(); 1644fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } finally { 1645fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.endTransaction(); 16465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.endTransaction(); 1647fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1648fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1649fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov updateLocaleInBackground(); 1650fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1651fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 165205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov protected void updateSearchIndexInBackground() { 165305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mSearchIndexManager.updateIndex(); 165405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 165505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1656bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateDirectoriesInBackground(boolean rescan) { 1657bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanAllPackages(rescan); 165851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 165951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 16603826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateProviderStatus() { 16613826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 16623826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 16633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return; 16643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16653826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 16663e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson // No accounts/no contacts status is true if there are no account and 16675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // there are no contacts or one profile contact 16683e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson if (mContactsAccountCount == 0) { 16695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactsNum = DatabaseUtils.queryNumEntries(mContactsHelper.getReadableDatabase(), 16703e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson Tables.CONTACTS, null); 16715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long profileNum = DatabaseUtils.queryNumEntries(mProfileHelper.getReadableDatabase(), 16725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Tables.CONTACTS, null); 16735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 16745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // TODO: Different status if there is a profile but no contacts? 16755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (contactsNum == 0 && profileNum <= 1) { 16763e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson setProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 16773e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson } else { 16783e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson setProviderStatus(ProviderStatus.STATUS_NORMAL); 16793e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson } 16803826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } else { 16813826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 16823826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16843826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 168531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1686f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro protected void cleanupPhotoStore() { 16875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); 16886802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 16896802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Assemble the set of photo store file IDs that are in use, and send those to the photo 1690f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // store. Any photos that aren't in that set will be deleted, and any photos that no 1691f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // longer exist in the photo store will be returned for us to clear out in the DB. 16927cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimeTypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 16936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Cursor c = db.query(Views.DATA, new String[]{Data._ID, Photo.PHOTO_FILE_ID}, 16947cf50494501938f175d288077145acf49da8f171Daniel Lehmann DataColumns.MIMETYPE_ID + "=" + photoMimeTypeId + " AND " 1695f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro + Photo.PHOTO_FILE_ID + " IS NOT NULL", null, null, null, null); 16966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Set<Long> usedPhotoFileIds = Sets.newHashSet(); 16976802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> photoFileIdToDataId = Maps.newHashMap(); 1698f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 1699f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro while (c.moveToNext()) { 17006802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long dataId = c.getLong(0); 17016802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long photoFileId = c.getLong(1); 17026802030a777c0c3ba1dc029c534cca4784260632Dave Santoro usedPhotoFileIds.add(photoFileId); 17036802030a777c0c3ba1dc029c534cca4784260632Dave Santoro photoFileIdToDataId.put(photoFileId, dataId); 17046802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 17056802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } finally { 17066802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.close(); 17076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 17086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 17096802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Also query for all social stream item photos. 1710c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro c = db.query(Tables.STREAM_ITEM_PHOTOS + " JOIN " + Tables.STREAM_ITEMS 1711c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " ON " + StreamItemPhotos.STREAM_ITEM_ID + "=" + StreamItemsColumns.CONCRETE_ID 1712c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " JOIN " + Tables.RAW_CONTACTS 1713c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " ON " + StreamItems.RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID, 17146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro new String[]{ 1715c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotosColumns.CONCRETE_ID, 1716c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID, 1717c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotos.PHOTO_FILE_ID, 1718c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro RawContacts.ACCOUNT_TYPE, 1719c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro RawContacts.ACCOUNT_NAME 17206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro }, 17216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro null, null, null, null, null); 17226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> photoFileIdToStreamItemPhotoId = Maps.newHashMap(); 17236802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> streamItemPhotoIdToStreamItemId = Maps.newHashMap(); 1724c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Map<Long, Account> streamItemPhotoIdToAccount = Maps.newHashMap(); 17256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 17266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro while (c.moveToNext()) { 17276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemPhotoId = c.getLong(0); 17286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemId = c.getLong(1); 17296802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long photoFileId = c.getLong(2); 1730c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro String accountType = c.getString(3); 1731c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro String accountName = c.getString(4); 17326802030a777c0c3ba1dc029c534cca4784260632Dave Santoro usedPhotoFileIds.add(photoFileId); 17336802030a777c0c3ba1dc029c534cca4784260632Dave Santoro photoFileIdToStreamItemPhotoId.put(photoFileId, streamItemPhotoId); 17346802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemPhotoIdToStreamItemId.put(streamItemPhotoId, streamItemId); 1735c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Account account = new Account(accountName, accountType); 1736c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro streamItemPhotoIdToAccount.put(photoFileId, account); 1737f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1738f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 1739f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 1740f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1741f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1742f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Run the photo store cleanup. 17435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> missingPhotoIds = mPhotoStore.get().cleanup(usedPhotoFileIds); 1744f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1745f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // If any of the keys we're using no longer exist, clean them up. 17466802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (!missingPhotoIds.isEmpty()) { 1747f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 17486802030a777c0c3ba1dc029c534cca4784260632Dave Santoro for (long missingPhotoId : missingPhotoIds) { 17496802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileIdToDataId.containsKey(missingPhotoId)) { 17506802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long dataId = photoFileIdToDataId.get(missingPhotoId); 1751f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues updateValues = new ContentValues(); 1752f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.putNull(Photo.PHOTO_FILE_ID); 1753f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ops.add(ContentProviderOperation.newUpdate( 17546802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ContentUris.withAppendedId(Data.CONTENT_URI, dataId)) 1755f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .withValues(updateValues).build()); 1756f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 17576802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileIdToStreamItemPhotoId.containsKey(missingPhotoId)) { 17586802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // For missing photos that were in stream item photos, just delete the stream 17596802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // item photo. 17606802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemPhotoId = photoFileIdToStreamItemPhotoId.get(missingPhotoId); 17616802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemId = streamItemPhotoIdToStreamItemId.get(streamItemPhotoId); 1762c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Account account = streamItemPhotoIdToAccount.get(missingPhotoId); 17636802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ops.add(ContentProviderOperation.newDelete( 17646802030a777c0c3ba1dc029c534cca4784260632Dave Santoro StreamItems.CONTENT_URI.buildUpon() 17656802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(String.valueOf(streamItemId)) 17666802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(StreamItems.StreamItemPhotos.CONTENT_DIRECTORY) 17676802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(String.valueOf(streamItemPhotoId)) 1768c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro .appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name) 1769c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro .appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type) 17706802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .build()).build()); 17716802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 1772f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1773f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 1774f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro applyBatch(ops); 1775f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } catch (OperationApplicationException oae) { 1776f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Not a fatal problem (and we'll try again on the next cleanup). 1777f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Log.e(TAG, "Failed to clean up outdated photo references", oae); 1778f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1779f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1780f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1781f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1782f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /* Visible for testing */ 1783de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1784b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1785b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 178631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 178731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 17885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public ProfileProvider getProfileProvider() { 17895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return new ProfileProvider(this); 17905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 17915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1792524913c66ce75ca8dec127ac88e3bc2249c246d9Dave Santoro @VisibleForTesting 1793f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /* package */ PhotoStore getPhotoStore() { 17945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mContactsPhotoStore; 1795f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1796f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 179787614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro /* package */ int getMaxDisplayPhotoDim() { 179887614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro return mMaxDisplayPhotoDim; 179987614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro } 180087614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro 180187614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro /* package */ int getMaxThumbnailPhotoDim() { 180287614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro return mMaxThumbnailPhotoDim; 180387614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro } 180487614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro 1805013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1806013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1807013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1808013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 18095df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov /* package */ NameLookupBuilder getNameLookupBuilder() { 18105df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov return mNameLookupBuilder; 18115df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov } 18125df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov 18135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 1814ed78fd6df5e9f3a2d572162e5d374d1f4a625bddDmitri Plotnikov public ContactDirectoryManager getContactDirectoryManagerForTest() { 181572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return mContactDirectoryManager; 181672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 181772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 181872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 18195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 18205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 18215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 18225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 18235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean applyingBatch() { 18245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Boolean applyingBatch = mApplyingBatch.get(); 18255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return applyingBatch != null && applyingBatch; 18265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 18275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 18285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean inProfileMode() { 18295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Boolean profileMode = mInProfileMode.get(); 18305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return profileMode != null && profileMode; 18315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 18325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 18333d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 18345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int version = Integer.parseInt( 18355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 1836b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 18373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18383d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1839568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1840568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1841568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1842568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1843568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1844bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Imports legacy contacts as a background task. 1845568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1846bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private void importLegacyContactsInBackground() { 1847bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 1848bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 1849568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1850bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setLocale(this, mCurrentLocale); 1852bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 1853568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1854bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1855bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (importLegacyContacts(importer)) { 1856bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportSuccess(); 1857bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } else { 1858bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportFailure(); 1859bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1860568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1861568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1862bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1863bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 1864bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1865bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 1866bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1867bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 1868bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 1869bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1870b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 18715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 1872b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 1873bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 1874bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 1875bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1876bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1877bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1878bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 1879bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1880bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 1881bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 1882bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1883bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 1884bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1885bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 1886bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 1887bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 1888bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 1889bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 1890bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 1891bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 1892bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 1893bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 1894bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1895bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 1896bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1897bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 1898bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 1899bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1900bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // Do not let any database changes until this issue is resolved. 1901bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mOkToOpenAccess = false; 19023d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19033d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 19043d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1905568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 19060e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 19073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 19083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 1909bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 1910bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1911bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1912bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 1913bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 1914bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 19153d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 19163d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 19173d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1918bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 1919bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 19203d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19213d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1922a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1923a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1924a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1925a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 19265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.wipeData(); 19275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper.wipeData(); 19285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore.clear(); 19295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore.clear(); 19303826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS; 1931a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1932a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1933568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 193415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov * During intialization, this content provider will 1935568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1936568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1937568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1938568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1939568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 194015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private void waitForAccess(CountDownLatch latch) { 194115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (latch == null) { 194215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 194315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 194415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 194515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov while (true) { 194615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov try { 194715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov latch.await(); 194815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 194915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } catch (InterruptedException e) { 195015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Thread.currentThread().interrupt(); 1951ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1952568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1953568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1954568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Determines whether the given URI should be directed to the profile 19575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database rather than the contacts database. This is true under either 19585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * of three conditions: 19595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 1. The URI itself is specifically for the profile. 19605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 2. The URI contains ID references that are in the profile ID-space. 19615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 3. The URI contains lookup key references that match the special profile lookup key. 19625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param uri The URI to examine. 19635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @return Whether to direct the DB operation to the profile database. 19645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 19655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean mapsToProfileDb(Uri uri) { 19665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return sUriMatcher.mapsToProfile(uri); 19675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 19695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Determines whether the given URI with the given values being inserted 19715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * should be directed to the profile database rather than the contacts 19725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database. This is true if the URI already maps to the profile DB from 19735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a call to {@link #mapsToProfileDb} or if the URI matches a URI that 19745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * specifies parent IDs via the ContentValues, and the given ContentValues 19755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * contains an ID in the profile ID-space. 19765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param uri The URI to examine. 19775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param values The values being inserted. 19785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @return Whether to direct the DB insert to the profile database. 19795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 19805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean mapsToProfileDbWithInsertedValues(Uri uri, ContentValues values) { 19815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 19825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return true; 19835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int match = sUriMatcher.match(uri); 19855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (INSERT_URI_ID_VALUE_MAP.containsKey(match)) { 19865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String idField = INSERT_URI_ID_VALUE_MAP.get(match); 19875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (values.containsKey(idField)) { 19885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long id = values.getAsLong(idField); 19895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (ContactsContract.isProfileId(id)) { 19905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return true; 19915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return false; 19955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 19975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Switches the provider's thread-local context variables to prepare for performing 19995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a profile operation. 20005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 20015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void switchToProfileMode() { 20025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mProfileHelper); 20035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.set(mProfileTransactionContext); 20045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.set(mProfileAggregator); 20055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mPhotoStore.set(mProfilePhotoStore); 20065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mInProfileMode.set(true); 20075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // If we're in batch mode and don't yet have a database set up for our transaction, 20095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // get one and start a transaction now. 20105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (applyingBatch() && mProfileDbForBatch.get() == null) { 20115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase profileDb = mProfileHelper.getWritableDatabase(); 20125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.beginTransactionWithListener(this); 20135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.set(profileDb); 20145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 20185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Switches the provider's thread-local context variables to prepare for performing 20195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a contacts operation. 20205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 20215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void switchToContactMode() { 20225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mContactsHelper); 20235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.set(mContactTransactionContext); 20245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.set(mContactAggregator); 20255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mPhotoStore.set(mContactsPhotoStore); 20265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mInProfileMode.set(false); 20275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // If not in batch mode, clear out the active database - it will be set to the default 20295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // instance from SQLiteContentProvider if necessary. 20305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (!applyingBatch()) { 20315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(null); 20325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 2035568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2036568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 203715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 20385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDbWithInsertedValues(uri, values)) { 2039072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2040072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2041072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.insert(uri, values); 2042072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2043072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2044072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2045072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2046072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro Uri result = null; 2047072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2048072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the insert using its provider. 2049072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2050072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.insert(uri, values); 2051072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2052072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2053072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2054072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2055072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2056072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2057072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2058072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2059072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 20605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 20615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 20625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.insert(uri, values); 20635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2064568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2065568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2066568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2067568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 206815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (mWriteAccessLatch != null) { 2069bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 2070bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 2071bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 2072bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 2073bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (match == PROVIDER_STATUS) { 2074bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 2075bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 2076bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 2077bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 2078bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2079bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 2080bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2081bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2082bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 208315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 20845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 2085072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2086072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2087072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.update(uri, values, selection, selectionArgs); 2088072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2089072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2090072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2091072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2092072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro int result = 0; 2093072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2094072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the update using its provider. 2095072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2096072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.update(uri, values, selection, selectionArgs); 2097072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2098072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2099072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2100072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2101072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2102072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2103072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2104072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2105072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 21065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 21075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 21085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.update(uri, values, selection, selectionArgs); 21095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2110568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2111568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2112568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2113568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 211415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 21155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 2116072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2117072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2118072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.delete(uri, selection, selectionArgs); 2119072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2120072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2121072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2122072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2123072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro int result = 0; 2124072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2125072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the delete using its provider. 2126072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2127072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.delete(uri, selection, selectionArgs); 2128072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2129072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2130072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2131072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2132072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2133072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2134072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2135072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2136072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 21375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 21385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 21395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.delete(uri, selection, selectionArgs); 21405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 21435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 21445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Replaces the current (thread-local) database to use for the operation with the given one. 21455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param db The database to use. 21465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 21475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /* package */ void substituteDb(SQLiteDatabase db) { 21485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 2149568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2150568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2151568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2152568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2153568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 215415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 21555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ContentProviderResult[] results = null; 21565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro try { 2157d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro mApplyingBatch.set(true); 21585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro results = super.applyBatch(operations); 21595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } finally { 2160d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro mApplyingBatch.set(false); 21615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mProfileDbForBatch.get() != null) { 21625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // A profile operation was involved, so clean up its transaction. 21635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro boolean profileErrors = mProfileErrorsInBatch.get() != null 21645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro && mProfileErrorsInBatch.get(); 21655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (!profileErrors) { 21665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.get().setTransactionSuccessful(); 21675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.get().endTransaction(); 21695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.set(null); 21705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileErrorsInBatch.set(false); 21715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return results; 2174568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2175568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 21764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 21777b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov public int bulkInsert(Uri uri, ContentValues[] values) { 21787b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov waitForAccess(mWriteAccessLatch); 2179720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro 2180720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro // Note: This duplicates much of the logic in the superclass, but handles toggling 2181720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro // into profile mode if necessary. 2182720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro int numValues = values.length; 2183720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro boolean notifyChange = false; 2184720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro SQLiteDatabase profileDb = null; 2185072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2186072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Always get a contacts DB and start a transaction on it, to maintain provider 2187072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // synchronization. 21888d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb = mContactsHelper.getWritableDatabase(); 21898d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.beginTransactionWithListener(this); 2190720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro try { 2191720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro for (int i = 0; i < numValues; i++) { 2192720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro Uri result; 2193720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (mapsToProfileDbWithInsertedValues(uri, values[i])) { 2194720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro switchToProfileMode(); 2195072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2196072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Initialize the profile DB and start a profile transaction if we haven't 2197072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // already done so. 2198720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb == null) { 2199720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb = mProfileHelper.getWritableDatabase(); 2200720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.beginTransactionWithListener(this); 2201720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2202720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro result = mProfileProvider.insertInTransaction(uri, values[i]); 2203720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } else { 2204720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro switchToContactMode(); 2205720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro result = insertInTransaction(uri, values[i]); 2206720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2207720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (result != null) { 2208720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange = true; 2209720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2210720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro boolean savedNotifyChange = notifyChange; 2211720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro mActiveDb.get().yieldIfContendedSafely(); 2212720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange = savedNotifyChange; 2213720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 22148d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.setTransactionSuccessful(); 2215720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb != null) { 2216720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.setTransactionSuccessful(); 2217720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2218720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } finally { 22198d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.endTransaction(); 2220720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb != null) { 2221720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.endTransaction(); 2222720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2223720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2224720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro 2225720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (notifyChange) { 2226720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange(); 2227720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2228720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro return numValues; 22297b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov } 22307b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov 22317b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov @Override 2232285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 2233bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2234b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 2235b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2236285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 22375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (inProfileMode()) { 22385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator.clearPendingAggregations(); 22395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileTransactionContext.clear(); 22405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 22415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator.clearPendingAggregations(); 22425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactTransactionContext.clear(); 22435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2244b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2245b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2246285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2247285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2248285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 22491129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 2250bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2251b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2252b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2253285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 2254b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 22555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateInTransaction(mTransactionContext.get(), mActiveDb.get()); 22561a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 22571a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 22585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateAllVisible(); 22591a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 22603826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2261bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 2262bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 22633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatusUpdateNeeded) { 22643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 22653826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = false; 22663826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 2267b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2268b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2269bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov private void updateSearchIndexInTransaction() { 22705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> staleContacts = mTransactionContext.get().getStaleSearchIndexContactIds(); 22715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> staleRawContacts = mTransactionContext.get().getStaleSearchIndexRawContactIds(); 2272bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov if (!staleContacts.isEmpty() || !staleRawContacts.isEmpty()) { 2273bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mSearchIndexManager.updateIndexForRawContacts(staleContacts, staleRawContacts); 22745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().clearSearchIndexUpdates(); 2275bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 2276bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 2277bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 2278b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2279bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2280b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2281b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 22821129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 22835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro for (long rawContactId : mTransactionContext.get().getInsertedRawContactIds()) { 22845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateRawContactDisplayName(mActiveDb.get(), rawContactId); 22855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().onRawContactInsert(mTransactionContext.get(), mActiveDb.get(), 22865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro rawContactId); 228724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 228824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 22895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> dirtyRawContacts = mTransactionContext.get().getDirtyRawContactIds(); 2290d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!dirtyRawContacts.isEmpty()) { 2291a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2292a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2293d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, dirtyRawContacts); 2294a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 22955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(mSb.toString()); 2296a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2297a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 22985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> updatedRawContacts = mTransactionContext.get().getUpdatedRawContactIds(); 2299d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!updatedRawContacts.isEmpty()) { 2300a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2301a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2302d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, updatedRawContacts); 2303a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 23045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(mSb.toString()); 2305b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2306b5a4add17815167d20a90645779df34cdf45280dFred Quintana 23075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Update sync states. 23085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro for (Map.Entry<Long, Object> entry : mTransactionContext.get().getUpdatedSyncStates()) { 2309b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 23105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().getSyncState().update(mActiveDb.get(), id, entry.getValue()) <= 0) { 23119d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 23129d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 23139d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 2314b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2315b5a4add17815167d20a90645779df34cdf45280dFred Quintana 23165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().clear(); 2317b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2318b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2319a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2320a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2321a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2322a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2323d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private void appendIds(StringBuilder sb, Set<Long> ids) { 2324b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2325a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2326b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2327a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2328a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2329285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2330285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2331285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2332cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 233381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 233481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 233581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 233681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 233781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 233881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 233981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2340cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2341568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 234251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 23433826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != status) { 23443826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = status; 23453826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov getContext().getContentResolver().notifyChange(ProviderStatus.CONTENT_URI, null, false); 23463826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 234751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 234851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2349f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public DataRowHandler getDataRowHandler(final String mimeType) { 23505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (inProfileMode()) { 23515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return getDataRowHandlerForProfile(mimeType); 23525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 23543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 23556d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov handler = new DataRowHandlerForCustomMimetype( 23565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro getContext(), mContactsHelper, mContactAggregator, mimeType); 23573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 23583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 23603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 23625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public DataRowHandler getDataRowHandlerForProfile(final String mimeType) { 23635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro DataRowHandler handler = mProfileDataRowHandlers.get(mimeType); 23645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (handler == null) { 23655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handler = new DataRowHandlerForCustomMimetype( 23665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro getContext(), mProfileHelper, mProfileAggregator, mimeType); 23675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDataRowHandlers.put(mimeType, handler); 23685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return handler; 23705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 23724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2373de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2374bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 23751129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2376b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2377f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 23785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 23795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 23805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 23815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 2383f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2384f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2385f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2386a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2387a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 238835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2389a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 239035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 23915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 23925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mDbHelper.get().getSyncState().insert(mActiveDb.get(), values); 239335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 239435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2395d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2396d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 23976bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 23986bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 23996bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 240024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 240124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro throw new UnsupportedOperationException( 240224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "The profile contact is created automatically"); 240324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 240424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 2405d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 2406d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 24075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = insertRawContact(uri, values, callerIsSyncAdapter); 2408f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2409a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2410a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2411a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2412d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 2413d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 2414d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 2415d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(segment)); 2416f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2417f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2418a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2419a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2420a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 24223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItems.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 24233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 24243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24280c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 24290c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 2430f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2431f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2432a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2433a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2434a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2435ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2436f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2437f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2438ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2439ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2440ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2441eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 24425aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 244343880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2444eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2445eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2446eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 24475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 24485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 244982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 24501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 24511f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24521f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 24533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 24543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 24553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 24603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 24613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 24663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItemPhotos.STREAM_ITEM_ID, uri.getPathSegments().get(1)); 24673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 24683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 2472a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 247381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2474f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2475a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2476a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 24787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 24797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24807e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2481de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2482a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2483a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2484a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2485e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2486e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2487e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2488e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2489e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2490e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2491e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2492e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2493e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2494e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2495e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2496e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2497e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 24987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2499e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2500f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2501f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2502e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2503f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2504f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2505f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2506e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2507e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2508e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2509e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2510e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 25115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 2512fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 2513e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2514e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2515e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2516e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2517e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2518e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2519e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2520e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2521e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2522e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2523e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2524e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 25255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 2526fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 2527e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2528e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2529e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2530f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2531f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2532e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2533f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2534f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2535e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2536e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2537f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2538f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2539e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2540f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2541f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2542f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2543f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2544035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2545f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2546e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 25477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 255043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Resolves the account and builds an {@link AccountWithDataSet} based on the data set specified 255143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * in the URI or values (if any). 255243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * @param uri Current {@link Uri} being operated on. 255343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * @param values {@link ContentValues} to read and possibly update. 255443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro */ 255543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private AccountWithDataSet resolveAccountWithDataSet(Uri uri, ContentValues values) { 25563593682b8d9213fde576a0cff54458ad50563980Dave Santoro final Account account = resolveAccount(uri, values); 255743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = null; 255843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (account != null) { 255943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 256043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (dataSet == null) { 25613593682b8d9213fde576a0cff54458ad50563980Dave Santoro dataSet = values.getAsString(RawContacts.DATA_SET); 2562a71dc460ca951c7aca591f3f470c160cde70a1e3Dave Santoro } else { 25633593682b8d9213fde576a0cff54458ad50563980Dave Santoro values.put(RawContacts.DATA_SET, dataSet); 256443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 256543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet = new AccountWithDataSet(account.name, account.type, dataSet); 256643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 256743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro return accountWithDataSet; 256843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 256943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 257043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro /** 2571d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 25726bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 25736bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 25746bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 25756bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2576d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2577de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 25786bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 25796bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 25806bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 258124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Inserts an item in the raw contacts table 2582a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2583f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2584f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2585dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param callerIsSyncAdapter 2586a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2587a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 25885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private long insertRawContact(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2589f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2590f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2591f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2592f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 259343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = resolveAccountWithDataSet(uri, mValues); 25947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25953d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 25963d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2597f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 25983d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 25993d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 26005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long rawContactId = mActiveDb.get().insert(Tables.RAW_CONTACTS, 26015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro RawContacts.CONTACT_ID, mValues); 2602f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 26035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 2604f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 2605f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 26065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markNewForAggregation(rawContactId, aggregationMode); 2607285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 26085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Trigger creation of a Contact based on this RawContact at the end of transaction 26095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactInserted(rawContactId, accountWithDataSet); 2610f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2611dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 2612dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 2613dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long starred = values.getAsLong(RawContacts.STARRED); 2614dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (starred != null && starred != 0) { 2615dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred != 0); 2616dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2617dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2618dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 26193826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 2620023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2621a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2622a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2623dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void addAutoAddMembership(long rawContactId) { 2624dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID, 2625dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2626dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2627dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2628dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2629dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2630dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2631dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private Long findGroupByRawContactId(String selection, long rawContactId) { 26325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS + "," + Tables.RAW_CONTACTS, 26335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROJECTION_GROUP_ID, selection, 2634dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}, 2635dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana null /* groupBy */, null /* having */, null /* orderBy */); 2636dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 2637dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 2638dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return c.getLong(0); 2639dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2640dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return null; 2641dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2642dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 2643dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2644dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2645dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2646dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateFavoritesMembership(long rawContactId, boolean isStarred) { 2647dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID, 2648dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2649dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2650dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (isStarred) { 2651dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2652dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2653dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana deleteDataGroupMembership(rawContactId, groupId); 2654dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2655dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2656dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2657dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2658dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void insertDataGroupMembership(long rawContactId, long groupId) { 2659dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues groupMembershipValues = new ContentValues(); 2660dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.GROUP_ROW_ID, groupId); 2661dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 2662dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(DataColumns.MIMETYPE_ID, 26635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 26645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().insert(Tables.DATA, null, groupMembershipValues); 2665dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2666dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2667dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void deleteDataGroupMembership(long rawContactId, long groupId) { 2668dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final String[] selectionArgs = { 26695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Long.toString(mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)), 2670dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(groupId), 2671dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(rawContactId)}; 26725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs); 2673dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2674dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2675a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2676a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2677a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2678a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2679a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2680a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2681f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2682a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2683de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2684de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 268567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2686de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 268720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2688de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2689de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2690de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 26915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 2692de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2693de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2694508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2695de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2696de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2697de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2698de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2699de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 27004097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 27015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.get().getMimeTypeId(mimeType)); 2702de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2703a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2704a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 27055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = rowHandler.insert(mActiveDb.get(), mTransactionContext.get(), rawContactId, mValues); 2706f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 27075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 2708a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 27095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactUpdated(rawContactId); 2710a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 27114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 27133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_items table. The account is checked against the 27153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account in the raw contact for which the stream item is being inserted. If the 27163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * new stream item results in more stream items under this raw contact than the limit, 27173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest one will be deleted (note that if the stream item inserted was the 27183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * oldest, it will be immediately deleted, and this will return 0). 27193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 27203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 27213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 27223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return the stream item _ID of the newly created row, or 0 if it was not created 27233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 27243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItem(Uri uri, ContentValues values) { 27253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 27263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 27273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 27283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = mValues.getAsLong(StreamItems.RAW_CONTACT_ID); 27303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 27323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 27333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 27343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27356802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to insert accounts params - they don't exist in the stream items table. 27366802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_NAME); 27376802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_TYPE); 27386802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 27393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Insert the new stream item. 27405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mActiveDb.get().insert(Tables.STREAM_ITEMS, null, mValues); 27416802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (id == -1) { 27426802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Insertion failed. 27436802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return 0; 27446802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check to see if we're over the limit for stream items under this raw contact. 27473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // It's possible that the inserted stream item is older than the the existing 27483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // ones, in which case it may be deleted immediately (resetting the ID to 0). 27493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = cleanUpOldStreamItems(rawContactId, id); 27503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 27523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_item_photos table. The account is checked against 27563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the account in the raw contact that owns the stream item being modified. 27573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 27583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 27593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 27606802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @return the stream item photo _ID of the newly created row, or 0 if there was an issue 27616802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * with processing the photo or creating the row 27623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 27633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItemPhoto(Uri uri, ContentValues values) { 27643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 27653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 27663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 27673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = mValues.getAsLong(StreamItemPhotos.STREAM_ITEM_ID); 27693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemId != 0) { 27703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = lookupRawContactIdForStreamId(streamItemId); 27713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 27733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 27743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 27753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to insert accounts params - they don't exist in the stream item 27776802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // photos table. 27786802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_NAME); 27796802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_TYPE); 27803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27816802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo and store it. 27826802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (processStreamItemPhoto(mValues, false)) { 27836802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Insert the stream item photo. 27845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mActiveDb.get().insert(Tables.STREAM_ITEM_PHOTOS, null, mValues); 27856802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 27883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27916802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * Processes the photo contained in the {@link ContactsContract.StreamItemPhotos#PHOTO} 27926802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * field of the given values, attempting to store it in the photo store. If successful, 27936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * the resulting photo file ID will be added to the values for insert/update in the table. 27946802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * <p> 27956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * If updating, it is valid for the picture to be empty or unspecified (the function will 27966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * still return true). If inserting, a valid picture must be specified. 27976802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @param values The content values provided by the caller. 27986802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @param forUpdate Whether this photo is being processed for update (vs. insert). 27996802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @return Whether the insert or update should proceed. 28006802030a777c0c3ba1dc029c534cca4784260632Dave Santoro */ 28016802030a777c0c3ba1dc029c534cca4784260632Dave Santoro private boolean processStreamItemPhoto(ContentValues values, boolean forUpdate) { 28026802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (!values.containsKey(StreamItemPhotos.PHOTO)) { 28036802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return forUpdate; 28046802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28056802030a777c0c3ba1dc029c534cca4784260632Dave Santoro byte[] photoBytes = values.getAsByteArray(StreamItemPhotos.PHOTO); 28066802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoBytes == null) { 28076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return forUpdate; 28086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28096802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 28106802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo and store it. 28116802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 28125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long photoFileId = mPhotoStore.get().insert(new PhotoProcessor(photoBytes, 28131dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim, true), true); 28146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileId != 0) { 28156802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.put(StreamItemPhotos.PHOTO_FILE_ID, photoFileId); 28166802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(StreamItemPhotos.PHOTO); 28176802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return true; 28186802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 28196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Couldn't store the photo, return 0. 28206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Log.e(TAG, "Could not process stream item photo for insert"); 28216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return false; 28226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28236802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } catch (IOException ioe) { 28246802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Log.e(TAG, "Could not process stream item photo for insert", ioe); 28256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return false; 28266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 28296802030a777c0c3ba1dc029c534cca4784260632Dave Santoro /** 28303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Looks up the raw contact ID that owns the specified stream item. 28313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param streamItemId The ID of the stream item. 28323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The associated raw contact ID, or -1 if no such stream item exists. 28333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long lookupRawContactIdForStreamId(long streamItemId) { 28353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = -1; 28365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, 28375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{StreamItems.RAW_CONTACT_ID}, 28383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems._ID + "=?", new String[]{String.valueOf(streamItemId)}, 28393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c.moveToFirst()) { 28423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann rawContactId = c.getLong(0); 28433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 28453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 28463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return rawContactId; 28483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 28513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given raw contact ID is owned by the given account. 28523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account is null, this will return true iff the raw contact 28533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * is also associated with the "null" account. 28543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 28553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account does not match, this will throw a security exception. 28563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 28573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to check for. 28583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void enforceModifyingAccount(Account account, long rawContactId) { 28603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String accountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 28613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + "=? AND " 28623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + "=?"; 28633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String noAccountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 28643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL AND " 28653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL"; 28663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c; 28673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (account != null) { 28685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c = mActiveDb.get().query(Tables.RAW_CONTACTS, 28695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{RawContactsColumns.CONCRETE_ID}, accountSelection, 28703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(rawContactId), mAccount.name, mAccount.type}, 28713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 28735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c = mActiveDb.get().query(Tables.RAW_CONTACTS, 28745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{RawContactsColumns.CONCRETE_ID}, noAccountSelection, 28755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{String.valueOf(rawContactId)}, 28763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if(c.getCount() == 0) { 28803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann throw new SecurityException("Caller account does not match raw contact ID " 28813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + rawContactId); 28823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 28843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 28853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 28893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream items matches up with the given 28903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 28913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 28923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 28933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 28943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 28953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item IDs that would be included in this selection. 28963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItems(Account account, String selection, 28983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 28993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = Lists.newArrayList(); 29003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 29013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 29025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), 29033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{StreamItems._ID, StreamItems.RAW_CONTACT_ID}, 29043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 29053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 29073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemIds.add(c.getLong(0)); 29083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 29103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 29113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds; 29163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream item photos matches up with the given 29203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 29213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 29223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 29233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 29243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 29253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item photo IDs that would be included in this selection. 29263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItemPhotos(Account account, String selection, 29283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 29293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemPhotoIds = Lists.newArrayList(); 29303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 29313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 29325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), 29335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{StreamItemPhotos._ID, StreamItems.RAW_CONTACT_ID}, 29343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 29353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 29373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemPhotoIds.add(c.getLong(0)); 29383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 29403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 29413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemPhotoIds; 29463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Queries the database for stream items under the given raw contact. If there are 29503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * more entries than {@link ContactsProvider2#MAX_STREAM_ITEMS_PER_RAW_CONTACT}, 29513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest entries (as determined by timestamp) will be deleted. 29523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to examine for stream items. 29533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param insertedStreamItemId The ID of the stream item that was just inserted, 29543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * prompting this cleanup. Callers may pass 0 if no insertion prompted the 29553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * cleanup. 29563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The ID of the inserted stream item if it still exists after cleanup; 29573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 0 otherwise. 29583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long cleanUpOldStreamItems(long rawContactId, long insertedStreamItemId) { 29603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long postCleanupInsertedStreamId = insertedStreamItemId; 29615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, new String[]{StreamItems._ID}, 29623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 29633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, StreamItems.TIMESTAMP + " DESC, " + StreamItems._ID + " DESC"); 29643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int streamItemCount = c.getCount(); 29663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemCount <= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 29673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Still under the limit - nothing to clean up! 29683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return insertedStreamItemId; 29693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 29703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToLast(); 29713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.getPosition() >= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 29723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = c.getLong(0); 29733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (insertedStreamItemId == streamItemId) { 29743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // The stream item just inserted is being deleted. 29753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann postCleanupInsertedStreamId = 0; 29763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(c.getLong(0)); 29783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToPrevious(); 29793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return postCleanupInsertedStreamId; 29853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 298820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 298920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2990f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 299120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 299220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2993de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2994de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 29950c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro Uri dataUri = inProfileMode() 29960c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro ? Uri.withAppendedPath(Profile.CONTENT_URI, RawContacts.Data.CONTENT_DIRECTORY) 29970c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro : Data.CONTENT_URI; 29980c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro Cursor c = query(dataUri, DataRowHandler.DataDeleteQuery.COLUMNS, 2999f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 3000de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 3001de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 3002f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID); 3003f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 3004a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 30055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count += rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c); 3006f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 30075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 300888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 300920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 301020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 3011de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 301220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 301320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 301420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 301520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 301620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 301788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 301888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 301988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 302020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 3021f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 302288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 302388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 30244da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 3025f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, Data._ID + "=?", 30264da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 3027f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 302820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 302920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 303020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 303120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 303220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3033f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 303420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 303520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 303620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 303720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 303820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 303920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 304020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 304120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 304220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 30437a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 304420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 304520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3046a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 30475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c); 304820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 304920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 305020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 305120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 305220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 305320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 3054ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 3055ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 3056f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 3057f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 3058f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 3059f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 30603593682b8d9213fde576a0cff54458ad50563980Dave Santoro final AccountWithDataSet accountWithDataSet = resolveAccountWithDataSet(uri, mValues); 3061ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3062ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 3063f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 306467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 30655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 306667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 3067f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 3068ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3069dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final boolean isFavoritesGroup = mValues.getAsLong(Groups.FAVORITES) != null 3070dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ? mValues.getAsLong(Groups.FAVORITES) != 0 3071dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana : false; 3072dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3073f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 3074f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 307573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 307673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 30775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long result = mActiveDb.get().insert(Tables.GROUPS, Groups.TITLE, mValues); 3078ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3079dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && isFavoritesGroup) { 3080dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // add all starred raw contacts to this group 3081dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String selection; 3082dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs; 30833593682b8d9213fde576a0cff54458ad50563980Dave Santoro if (accountWithDataSet == null) { 3084dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + " IS NULL AND " 308543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.ACCOUNT_TYPE + " IS NULL AND " 308643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.DATA_SET + " IS NULL"; 3087dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = null; 30883593682b8d9213fde576a0cff54458ad50563980Dave Santoro } else if (accountWithDataSet.getDataSet() == null) { 3089dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + "=? AND " 30903593682b8d9213fde576a0cff54458ad50563980Dave Santoro + RawContacts.ACCOUNT_TYPE + "=? AND " 30913593682b8d9213fde576a0cff54458ad50563980Dave Santoro + RawContacts.DATA_SET + " IS NULL"; 30923593682b8d9213fde576a0cff54458ad50563980Dave Santoro selectionArgs = new String[] { 30933593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountName(), 30943593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountType() 30953593682b8d9213fde576a0cff54458ad50563980Dave Santoro }; 309643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } else { 309743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro selection = RawContacts.ACCOUNT_NAME + "=? AND " 309843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.ACCOUNT_TYPE + "=? AND " 309943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.DATA_SET + "=?"; 31003593682b8d9213fde576a0cff54458ad50563980Dave Santoro selectionArgs = new String[] { 31013593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountName(), 31023593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountType(), 31033593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getDataSet() 31043593682b8d9213fde576a0cff54458ad50563980Dave Santoro }; 3105dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 31065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3107dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{RawContacts._ID, RawContacts.STARRED}, 3108dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, selectionArgs, null, null, null); 3109892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov try { 3110892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov while (c.moveToNext()) { 3111892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (c.getLong(1) != 0) { 3112892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov final long rawContactId = c.getLong(0); 3113892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov insertDataGroupMembership(rawContactId, result); 31145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 3115892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 3116dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3117892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } finally { 3118892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov c.close(); 3119dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3120dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3121dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3122f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 31231a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3124ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 3125ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3126ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 3127ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3128ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31295aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 3130f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // Before inserting, ensure that no settings record already exists for the 3131f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // values being inserted (this used to be enforced by a primary key, but that no 3132f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // longer works with the nullable data_set field added). 3133f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String accountName = values.getAsString(Settings.ACCOUNT_NAME); 3134f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String accountType = values.getAsString(Settings.ACCOUNT_TYPE); 3135f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String dataSet = values.getAsString(Settings.DATA_SET); 3136f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro Uri.Builder settingsUri = Settings.CONTENT_URI.buildUpon(); 3137f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (accountName != null) { 3138f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.ACCOUNT_NAME, accountName); 3139f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3140f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (accountType != null) { 3141f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.ACCOUNT_TYPE, accountType); 3142f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3143f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet != null) { 3144f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.DATA_SET, dataSet); 3145f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3146f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro Cursor c = queryLocal(settingsUri.build(), null, null, null, null, 0); 3147f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro try { 3148f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (c.getCount() > 0) { 31490e21a867a572679d64d79041eb574d13665178d4Dave Santoro // If a record was found, replace it with the new values. 31500e21a867a572679d64d79041eb574d13665178d4Dave Santoro String selection = null; 31510e21a867a572679d64d79041eb574d13665178d4Dave Santoro String[] selectionArgs = null; 31520e21a867a572679d64d79041eb574d13665178d4Dave Santoro if (accountName != null && accountType != null) { 31530e21a867a572679d64d79041eb574d13665178d4Dave Santoro selection = Settings.ACCOUNT_NAME + "=? AND " + Settings.ACCOUNT_TYPE + "=?"; 31540e21a867a572679d64d79041eb574d13665178d4Dave Santoro if (dataSet == null) { 31550e21a867a572679d64d79041eb574d13665178d4Dave Santoro selection += " AND " + Settings.DATA_SET + " IS NULL"; 31560e21a867a572679d64d79041eb574d13665178d4Dave Santoro selectionArgs = new String[] {accountName, accountType}; 31570e21a867a572679d64d79041eb574d13665178d4Dave Santoro } else { 31580e21a867a572679d64d79041eb574d13665178d4Dave Santoro selection += " AND " + Settings.DATA_SET + "=?"; 31590e21a867a572679d64d79041eb574d13665178d4Dave Santoro selectionArgs = new String[] {accountName, accountType, dataSet}; 31600e21a867a572679d64d79041eb574d13665178d4Dave Santoro } 31610e21a867a572679d64d79041eb574d13665178d4Dave Santoro } 31620e21a867a572679d64d79041eb574d13665178d4Dave Santoro return updateSettings(uri, values, selection, selectionArgs); 3163f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3164f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } finally { 3165f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro c.close(); 3166f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3167f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro 3168f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // If we didn't find a duplicate, we're fine to insert. 31695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long id = mActiveDb.get().insert(Tables.SETTINGS, null, values); 31705aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 31711a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 31721a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3173e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 31741a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 3175e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 3176e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3177e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3178ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 317982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 31801f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 318182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 318282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 31830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 31844dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 31854dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 31860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 318782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 31884dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 31894dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 31904dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 31914dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 31921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3194dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 3195dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 319682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 31976802030a777c0c3ba1dc029c534cca4784260632Dave Santoro String accountType = null; 31986802030a777c0c3ba1dc029c534cca4784260632Dave Santoro String accountName = null; 3199f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 32002526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 3201dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 3202dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 3203dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 32042526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 32052526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 32061f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 3207dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 3208dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 32090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 32100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 32110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 32120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3213dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 3214dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 3215dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 32165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String mimeTypeIdIm = String.valueOf(mDbHelper.get().getMimeTypeIdForIm()); 3217dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 32185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String mimeTypeIdEmail = String.valueOf(mDbHelper.get().getMimeTypeIdForEmail()); 3219f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3220f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 3221f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 3222f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 3223f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3224f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 3225f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 32262526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 32272526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 32282526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 32292526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 32302526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32312526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 32322526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32332526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 3234dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32352526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32362526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3237dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32382526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 32392526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 3240dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 32412526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 32422526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 32432526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 32442526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32452526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 32462526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 3247dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32482526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32492526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3250dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 3251dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32521f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 325382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 32542526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 32552526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 3256dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 325770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 325870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 32591f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 32601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 32615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cursor = mActiveDb.get().query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 32622526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 32634394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID); 32641f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 326567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 32665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 32676802030a777c0c3ba1dc029c534cca4784260632Dave Santoro accountType = cursor.getString(DataContactsQuery.ACCOUNT_TYPE); 32686802030a777c0c3ba1dc029c534cca4784260632Dave Santoro accountName = cursor.getString(DataContactsQuery.ACCOUNT_NAME); 3269e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 32701f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 32711f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 32721f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 32731f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32741f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 327531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 327631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 327731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 32781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 328082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 3281a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 3282a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 3283a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 3284a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 3285a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3286a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3287a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 328882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 3289a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 3290a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 329182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 329282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 329382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 329482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 329582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 3296a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 329782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 329882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 3299aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori mValues.put(StatusUpdates.CHAT_CAPABILITY, 3300aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori values.getAsString(StatusUpdates.CHAT_CAPABILITY)); 33011f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3302a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 33035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().replace(Tables.PRESENCE, null, mValues); 3304a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3305e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 33060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 330782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 330882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 33090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 33100bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Resources resources = getContext().getResources(); 33110bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (!TextUtils.isEmpty(resPackage)) { 33120bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann PackageManager pm = getContext().getPackageManager(); 33130bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann try { 33140bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann resources = pm.getResourcesForApplication(resPackage); 33150bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } catch (NameNotFoundException e) { 33160bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Log.w(TAG, "Contact status update resource package not found: " 33170bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + resPackage); 33180bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33190bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33200bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Integer labelResourceId = values.getAsInteger(StatusUpdates.STATUS_LABEL); 33210a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33220bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if ((labelResourceId == null || labelResourceId == 0) && protocol != null) { 33230bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann labelResourceId = Im.getProtocolLabelResource(protocol); 33240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 33250bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann String labelResource = getResourceName(resources, "string", labelResourceId); 33260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33270bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Integer iconResourceId = values.getAsInteger(StatusUpdates.STATUS_ICON); 33280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 33290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33300bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann String iconResource = getResourceName(resources, "drawable", iconResourceId); 33310bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 3332a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 33335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().deleteStatusUpdate(dataId); 3334a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 33356802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 33366802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (timestamp != null) { 33375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().replaceStatusUpdate(dataId, timestamp, status, resPackage, 33380bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann iconResourceId, labelResourceId); 33396802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 33405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().insertStatusUpdate(dataId, status, resPackage, iconResourceId, 33410bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann labelResourceId); 33426802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33436802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33446802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // For forward compatibility with the new stream item API, insert this status update 33456802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // there as well. If we already have a stream item from this source, update that 33466802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // one instead of inserting a new one (since the semantics of the old status update 33476802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // API is to only have a single record). 33486802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (rawContactId != -1 && !TextUtils.isEmpty(status)) { 33496802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ContentValues streamItemValues = new ContentValues(); 33506802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3351d5ef5903570e533a501abe6a8e3d533fdb5318fcFlavio Lerda // Status updates are text only but stream items are HTML. 3352e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda streamItemValues.put(StreamItems.TEXT, statusUpdateToHtml(status)); 33536802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.COMMENTS, ""); 33546802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_PACKAGE, resPackage); 33556802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_ICON, iconResource); 33566802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_LABEL, labelResource); 33576802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.TIMESTAMP, 33586802030a777c0c3ba1dc029c534cca4784260632Dave Santoro timestamp == null ? System.currentTimeMillis() : timestamp); 33596802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33606802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Note: The following is basically a workaround for the fact that status 33616802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // updates didn't do any sort of account enforcement, while social stream item 33626802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // updates do. We can't expect callers of the old API to start passing account 33636802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // information along, so we just populate the account params appropriately for 336443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // the raw contact. Data set is not relevant here, as we only check account 336543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // name and type. 33666802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (accountName != null && accountType != null) { 33676802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(RawContacts.ACCOUNT_NAME, accountName); 33686802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(RawContacts.ACCOUNT_TYPE, accountType); 33696802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33706802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33716802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Check for an existing stream item from this source, and insert or update. 33726802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Uri streamUri = StreamItems.CONTENT_URI; 33736802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Cursor c = query(streamUri, new String[]{StreamItems._ID}, 33746802030a777c0c3ba1dc029c534cca4784260632Dave Santoro StreamItems.RAW_CONTACT_ID + "=?", 33756802030a777c0c3ba1dc029c534cca4784260632Dave Santoro new String[]{String.valueOf(rawContactId)}, null); 33766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 33776802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (c.getCount() > 0) { 33786802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.moveToFirst(); 33796802030a777c0c3ba1dc029c534cca4784260632Dave Santoro update(ContentUris.withAppendedId(streamUri, c.getLong(0)), 33806802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues, null, null); 33816802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 33826802030a777c0c3ba1dc029c534cca4784260632Dave Santoro insert(streamUri, streamItemValues); 33836802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } finally { 33856802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.close(); 33866802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33876802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 3388e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3389e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3390bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3391a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 33925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLastStatusUpdateId(contactId); 3393a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3394a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3395a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 33961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 33971f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3398e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda /** Converts a status update to HTML. */ 3399e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda private String statusUpdateToHtml(String status) { 34004747809486541f7a3d342d3e1dd48fb5ea255ad6Flavio Lerda return TextUtils.htmlEncode(status); 3401e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda } 3402e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda 34030bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann private String getResourceName(Resources resources, String expectedType, Integer resourceId) { 34040bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann try { 34050bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (resourceId == null || resourceId == 0) return null; 34060bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 34070bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann // Resource has an invalid type (e.g. a string as icon)? ignore 34080bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann final String resourceEntryName = resources.getResourceEntryName(resourceId); 34090bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann final String resourceTypeName = resources.getResourceTypeName(resourceId); 34100bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (!expectedType.equals(resourceTypeName)) { 34110bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Log.w(TAG, "Resource " + resourceId + " (" + resourceEntryName + ") is of type " + 34120bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann resourceTypeName + " but " + expectedType + " is required."); 34130bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return null; 34140bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34150bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 34160bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return resourceEntryName; 34170bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } catch (NotFoundException e) { 34180bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return null; 34190bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34200bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34210bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 34224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3423de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 3424bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3425b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 3426b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 34275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 34285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 34295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 34305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 34315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 34325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 3433b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3434f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3435f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 3436508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 3437508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 343835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 34395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 34405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selection, 34415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 34435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case SYNCSTATE_ID: { 34445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String selectionWithId = 34455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 34465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 34475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selectionWithId, 34485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 345035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 34515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE_ID: { 3452b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3453b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3454b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 34555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getSyncState().delete(mActiveDb.get(), selectionWithId, 34565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 3458b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3459cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 3460cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 3461cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 3462cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3463cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3464d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3465d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3466dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34676bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 34686bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 34699fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 34702e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 34712e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 34722e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 34735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 3474fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 34752e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34762e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 34775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 3478dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34792e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34802e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 34819fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 34829fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 34839fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 34849fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 34859fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 34869fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 3487a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 34889fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 34899fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 34909fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 34919fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34929fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 34939fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 34949fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34959fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 349660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 34979fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 34985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = query(mActiveDb.get(), lookupQb, null, selection, args, null, null, 34995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null); 35009fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 35019fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 35029fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 3503dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 35049fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 35059fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 35069fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 35079fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 35089fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 35099fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 35109fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 35119fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 35129fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 35139fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 3514d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 3515d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 35162971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 35175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3518fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 3519e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 35202971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 35212971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 35222971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 3523fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 3524fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 3525fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 35262971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35272971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 35282971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 35292971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35302971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 35312971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35322971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 3533d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_ID: 3534d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID: { 35352971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 35365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return deleteRawContact(rawContactId, mDbHelper.get().getContactId(rawContactId), 3537fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 3538508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3539508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 35400c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 35410c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 3542f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 3543944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 3544f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 354520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 354620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 354748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 354848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 354948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 3550d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case POSTALS_ID: 3551d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA_ID: { 3552508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3553f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 35544da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 35554da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 3556ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3557ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3558ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3559f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 35605aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 35612971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35622971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 35632971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 35642971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 35655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS, new String[]{Groups._ID}, 3566e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 35672971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 35682971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 35695aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 35702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 35722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 35732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 357481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3575f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 357681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 35772971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3578508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3579508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3580eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 358143880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3582e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3583eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3584eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 35855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 35865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 35870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 35881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 35891f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 35903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 35913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), selection, selectionArgs); 35933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 35943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 35953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 35963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), 35989b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann StreamItems._ID + "=?", 35993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 36003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 360282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 360382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro mSyncToNetwork |= !callerIsSyncAdapter; 360482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String rawContactId = uri.getPathSegments().get(1); 360582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String streamItemId = uri.getLastPathSegment(); 360682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro return deleteStreamItems(uri, new ContentValues(), 360782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=? AND " + StreamItems._ID + "=?", 360882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{rawContactId, streamItemId}); 360982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 361082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 361182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 36123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 36133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 36145d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro String streamItemId = uri.getPathSegments().get(1); 36155d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro String selectionWithId = 36165d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro (StreamItemPhotos.STREAM_ITEM_ID + "=" + streamItemId + " ") 36175d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 36185d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro return deleteStreamItemPhotos(uri, new ContentValues(), 36195d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro selectionWithId, selectionArgs); 36203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 36223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 36233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 36243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 36253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 36263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItemPhotos(uri, new ContentValues(), 36273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " 36283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + StreamItemPhotos.STREAM_ITEM_ID + "=?", 36293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 36303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 363281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 363381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 36343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 363581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3636508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 36374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36384f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36391c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3640ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 36415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long groupMembershipMimetypeId = mDbHelper.get() 364294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 36435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 364494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 364594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 364694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 364794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3648f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 36495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 365094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 365194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 365294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3653f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 36545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, 36555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null); 365694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 365794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 36581a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 365994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 366094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 366194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 36625aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 36635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final int count = mActiveDb.get().delete(Tables.SETTINGS, selection, selectionArgs); 36641a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3665e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3666e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3667e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3668dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int deleteContact(long contactId, boolean callerIsSyncAdapter) { 366996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 36705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 367196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 367296b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 3673cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3674cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3675cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3676dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 3677cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3678cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3679cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3680cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3681cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 36823826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 36833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 36845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3685cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3686cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3687fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 36885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().invalidateAggregationExceptionCache(); 36893826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 36903826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 369182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro // Find and delete stream items associated with the raw contact. 369282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, 369382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{StreamItems._ID}, 369482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 369582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro null, null, null); 369682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro try { 369782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro while (c.moveToNext()) { 369882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro deleteStreamItem(c.getLong(0)); 369982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 370082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } finally { 370182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro c.close(); 370282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 370382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 3704d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro if (callerIsSyncAdapter || rawContactIsLocal(rawContactId)) { 37055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.PRESENCE, 37065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 37075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().delete(Tables.RAW_CONTACTS, 37085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro RawContacts._ID + "=" + rawContactId, null); 37095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateDisplayNameForContact(mActiveDb.get(), contactId); 3710fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 371133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 37125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().removeContactIfSingleton(rawContactId); 3713dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 371433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 371533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 371633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3717d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro /** 3718d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro * Returns whether the given raw contact ID is local (i.e. has no account associated with it). 3719d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro */ 3720d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro private boolean rawContactIsLocal(long rawContactId) { 3721d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3722d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro new String[] { 3723d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.ACCOUNT_NAME, 3724d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.ACCOUNT_TYPE, 3725d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.DATA_SET 3726d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro }, 3727d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts._ID + "=?", 3728d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro new String[] {String.valueOf(rawContactId)}, null, null, null); 3729d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro try { 3730d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro return c.moveToFirst() && c.isNull(0) && c.isNull(1) && c.isNull(2); 3731d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } finally { 3732d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro c.close(); 3733d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } 3734d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } 3735d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro 37360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 37379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 37389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 37399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 37409705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 37419705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 37439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 37445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.PRESENCE, selection, selectionArgs); 37450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 37460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 37473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItems(Uri uri, ContentValues values, String selection, 37483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 37493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream items to be deleted, and check that they belong 37503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // to the account. 37513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 37523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = enforceModifyingAccountForStreamItems( 37533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann account, selection, selectionArgs); 37543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 37563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann for (long streamItemId : streamItemIds) { 37573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(streamItemId); 37583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mVisibleTouched = true; 37613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds.size(); 37623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItem(long streamItemId) { 37653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 37663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItemPhotos(streamItemId); 37675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEMS, StreamItems._ID + "=?", 37683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 37693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(Uri uri, ContentValues values, String selection, 37723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 37733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream item photos to be deleted, and check that they 37743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // belong to the account. 37753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 37763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 37773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 37795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, selection, selectionArgs); 37803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(long streamItemId) { 37833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 37845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, 37855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro StreamItemPhotos.STREAM_ITEM_ID + "=?", 37863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 37873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 3789dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) { 379081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 379181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3792cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3793cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3794cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3795cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3796cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3797cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3798dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues, callerIsSyncAdapter); 3799cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3800cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 38014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3802de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3803de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3804bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3805b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3806b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3807b5a4add17815167d20a90645779df34cdf45280dFred Quintana 38085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 38095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 38105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 38115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 38125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 381335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 381400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 381500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3816b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3817b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 38181129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 38195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().syncStateUpdated(rowId, data); 3820b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3821b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3822b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3823f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3824f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 382500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 382635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 38275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 38285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().update(mActiveDb.get(), values, 3829b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3830b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3831b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3832b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3833b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3834b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3835b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 38365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().update(mActiveDb.get(), values, 38375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionWithId, selectionArgs); 38385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 38395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 38405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE_ID: { 38415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection = appendAccountToSelection(uri, selection); 38425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String selectionWithId = 38435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 38445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 38455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getSyncState().update(mActiveDb.get(), values, 3846b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3847b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 384835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3849d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case CONTACTS: 3850d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE: { 3851dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 385200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 385300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 385400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3855d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3856dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter); 3857c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3858c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3859c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 38602e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 38612e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 38622e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 38632e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 38642e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 38655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 3866fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 38672e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 38682e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 38695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 3870dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(contactId, values, callerIsSyncAdapter); 38712e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 38722e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 38732e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 3874d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 3875d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 3876d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 3877d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro final String rawContactId = uri.getPathSegments().get(segment); 38787d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 38797d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 38807d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38817d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 38827d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38837d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 38847d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 38857d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38860c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 38870c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 3888944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3889f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 389081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3891f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 389281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 389320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 389420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3895c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 389648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 389748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 389848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 389948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3900f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 390181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3902f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 390381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 390400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 390500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 39067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case RAW_CONTACTS: 39085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_RAW_CONTACTS: { 39095ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 3910dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, selection, selectionArgs, callerIsSyncAdapter); 39117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 39127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 391533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 39164529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 39174da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 39184da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 3919dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND(" + selection + ")", selectionArgs, 3920dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 39214529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 39224da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 3923dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1, 3924dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 39254529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 39267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 39277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3929ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 39305aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3931f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 393281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3933f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 393481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3935ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3936ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3937ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3938ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3939ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 39404da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 39414da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 394273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 39435aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 39445aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 394581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3946f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 394781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3948ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3949ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3950ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3951127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 39525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count = updateAggregationException(mActiveDb.get(), values); 3953b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3954b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3955b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3956eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3957e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3958e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 395943880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3960eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3961eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3962eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 39635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 39645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 39659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 39669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 39679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 39689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 39693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 39703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItems(uri, values, selection, selectionArgs); 39713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 39759b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann count = updateStreamItems(uri, values, StreamItems._ID + "=?", 39763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 39773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 398082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 398182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String rawContactId = uri.getPathSegments().get(1); 398282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String streamItemId = uri.getLastPathSegment(); 398382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro count = updateStreamItems(uri, values, 398482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=? AND " + StreamItems._ID + "=?", 398582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{rawContactId, streamItemId}); 398682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro break; 398782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 398882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 39893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 39903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, selection, selectionArgs); 39913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 39953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 39963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 39973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotos.STREAM_ITEM_ID + "=?", new String[]{streamItemId}); 39983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 40023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 40033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 40043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 40053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " + 40063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?", 40073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 40083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 40093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 401172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case DIRECTORIES: { 4012bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanPackagesByUid(Binder.getCallingUid()); 401372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov count = 1; 4014d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 4015d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4016d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 401746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa case DATA_USAGE_FEEDBACK_ID: { 401846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (handleDataUsageFeedback(uri)) { 401946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 1; 402046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 402146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 0; 402246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 402346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa break; 402446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 402546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 402681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 402781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 4028f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 402981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 403000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 403100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 403200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 40334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 40344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 40359705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 40369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 40379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 40389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 40399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 40409705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 40419705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 40425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro updateCount = mActiveDb.get().update(Tables.STATUS_UPDATES, 40439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 40449705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 40459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 40469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40479705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40489705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 40499705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 40509705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 40515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro updateCount = mActiveDb.get().update(Tables.PRESENCE, settableValues, 40529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 40539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 40559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 40569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 40579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItems(Uri uri, ContentValues values, String selection, 40603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 40613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream items can't be moved to a new raw contact. 40623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItems.RAW_CONTACT_ID); 40633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream items being updated belong to the account. 40653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 40663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItems(account, selection, selectionArgs); 40673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40686802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to update accounts params - they don't exist in the stream items table. 40696802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_NAME); 40706802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_TYPE); 40716802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 40723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If there's been no exception, the update should be fine. 40735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.STREAM_ITEMS, values, selection, selectionArgs); 40743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItemPhotos(Uri uri, ContentValues values, String selection, 40773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 40783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream item photos can't be moved to a new stream item. 40793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItemPhotos.STREAM_ITEM_ID); 40803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream item photos being updated belong to the account. 40823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 40833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 40843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40856802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to update accounts params - they don't exist in the stream item 40866802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // photos table. 40876802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_NAME); 40886802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_TYPE); 40896802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 40906802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo (since we're updating, it's valid for the photo to not be present). 40916802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (processStreamItemPhoto(values, true)) { 40926802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // If there's been no exception, the update should be fine. 40935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.STREAM_ITEM_PHOTOS, values, selection, 40945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 40956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 40966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return 0; 40973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 41009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 41019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 41029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 41039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 41049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 41059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 41069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 41079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 41089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 41099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 41119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 41129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 41139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 41149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 41159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 41169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 41179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 41189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 41199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 41209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 41219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 41229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 41239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 41249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 41269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 41279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 41289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 4129aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.CHAT_CAPABILITY, values, 4130aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori StatusUpdates.CHAT_CAPABILITY); 41319705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 41329705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 41339705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41345aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 4135f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 413673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4137ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 4138ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 413973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 4140f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 414173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 414273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 414373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 414473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 414573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 414673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 414773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 414873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 41495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().update(Tables.GROUPS, updatedValues, selectionWithId, 41505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 41511a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 41521a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 415394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 415443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 415543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO: This will not work for groups that have a data set specified, since the content 415643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // resolver will not be able to request a sync for the right source (unless it is updated 415743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // to key off account with data set). 41586ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 41591129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 41605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 4161e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 41626ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 41636ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 41646ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 41656ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 41666ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 41676ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 41686ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 416924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 41706ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 4171ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 41726ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 41736ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 41746ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41756ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41766ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 41776ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 41786ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41796ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 418094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 418194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 418294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 4183b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 4184b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 41855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final int count = mActiveDb.get().update(Tables.SETTINGS, values, selection, selectionArgs); 41861a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 41871a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 4188e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4189e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 4190e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4191e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4192dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs, 4193dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 41944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 41954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 41964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 41974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 419873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 419997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 420097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 420197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0"); 420297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 420397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 42044529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 42055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS, 420651bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 42074529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 42084529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 42094529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 42104529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 4211dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContact(rawContactId, values, callerIsSyncAdapter); 42124529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 42134529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 42144529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 42154529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 42164529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 42174529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 42184529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 42194529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 42204529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 4221dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContact(long rawContactId, ContentValues values, 4222dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 422396b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 422496b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 422519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 422619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 422719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 4228ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 4229ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 423043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet = null; 423119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 42325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 42335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, mSelectionArgs1, null, null, null); 423419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 423519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 423619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 4237ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 4238ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 423943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro dataSet = cursor.getString(RawContactsQuery.DATA_SET); 424019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 424119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 424219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 424319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 424419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 424519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 424619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 4247f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 42485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 42495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 4250f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 4251f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 4252f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 4253f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 4254f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 4255f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 42565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId, aggregationMode, false); 4257f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 4258f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 4259433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 4260dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 4261dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4262dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana values.getAsLong(RawContacts.STARRED) != 0); 4263dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 42645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateStarred(rawContactId); 4265dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 4266dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then update the 4267dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // favorites group membership based on whether or not this contact is starred. 4268dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // If it is starred, add a group membership, if one doesn't already exist 4269dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // otherwise delete any matching group memberships. 4270dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 42715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro boolean starred = 0 != DatabaseUtils.longForQuery(mActiveDb.get(), 4272dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SELECTION_STARRED_FROM_RAW_CONTACTS, 4273dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}); 4274dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred); 4275dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4276dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4277dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 4278dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then add a 4279dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // group membership to the group marked as AutoAdd, if any. 4280dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 4281dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 4282433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 4283dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 4284285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 42855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLookupKeyForRawContact(mActiveDb.get(), rawContactId); 4286285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 4287f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 4288f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 4289f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 4290f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 4291f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 42925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().resetNameVerifiedForOtherRawContacts(rawContactId); 4293f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 42945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateDisplayNameForRawContact(mActiveDb.get(), rawContactId); 4295f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 429619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 42975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactInserted(rawContactId, 429843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new AccountWithDataSet(accountName, accountType, dataSet)); 429919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 43005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 430233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 430333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 4304321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 4305f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 430620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 430720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 430820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 43095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 431020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 431120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 431220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 431320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 431420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 43155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 431620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 431720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 431897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 431997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 432097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov Data.IS_READ_ONLY + "=0"); 432197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 432297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 4323653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 432420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4325653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 4326653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 43275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryLocal(uri, 4328f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro DataRowHandler.DataUpdateQuery.COLUMNS, 43295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, selectionArgs, null, -1 /* directory ID */); 4330653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 4331653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 4332f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 433320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 4334653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 4335653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 433620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 433720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4338653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 433920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 434020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4341f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 4342653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 4343653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 4344321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4345653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 4346f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String mimeType = c.getString(DataRowHandler.DataUpdateQuery.MIMETYPE); 4347a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 4348f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro boolean updated = 43495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro rowHandler.update(mActiveDb.get(), mTransactionContext.get(), values, c, 43505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro callerIsSyncAdapter); 4351f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) { 4352f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 4353a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 4354f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return updated ? 1 : 0; 4355321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4356321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 43578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 4358dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 43598c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 43605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.CONTACTS, 43615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[] { Contacts._ID }, selection, selectionArgs, null, null, null); 43628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 43638c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 43648c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 436524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 4366dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateContactOptions(contactId, values, callerIsSyncAdapter); 43678c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 43688c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 43698c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 43708c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 43718c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 43728c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 43738c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 43748c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 43758c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4376dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateContactOptions(long contactId, ContentValues values, 4377dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 4378d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 43798c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4380b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 4381d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4382b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 4383d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4384b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 4385d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4386b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 4387d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4388b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 4389d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 4390d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4391d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 43928c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 4393d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 4394d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 4395d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 43968c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 4397c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 43988c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 4399c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 4400c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 44014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 44025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?" 440397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov + " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1); 44048c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4405dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) { 44065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS, 4407dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?", 4408dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null, null, null); 4409dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 4410dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (cursor.moveToNext()) { 4411dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long rawContactId = cursor.getLong(0); 4412dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4413dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.getAsLong(RawContacts.STARRED) != 0); 4414dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4415dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 4416dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana cursor.close(); 4417dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4418dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4419dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 44208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 44218c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 44228c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4423b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 44248c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4425b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 44268c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4427b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 44288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4429b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 44308c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4431b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 44328c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 44338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 44345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int rslt = mActiveDb.get().update(Tables.CONTACTS, mValues, Contacts._ID + "=?", 44355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mSelectionArgs1); 44366e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 44379b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 44389b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 44395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 44405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 44419b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 44429b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 4443f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 4444d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4445127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 4446127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 44470c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 44480c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 444980c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 4450ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId1; 4451ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId2; 44520c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 44530c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 44540c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 44550c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 44560c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 44570c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 4458b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4459127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 44600c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 44614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 44624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 44630c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 44644da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 44654da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 44660c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 44676bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 44686bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 44690c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 44700c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 44710c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 44720c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 4473127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 4474127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 44755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().invalidateAggregationExceptionCache(); 44765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId1, 447769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 44785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId2, 447969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 4480dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 44815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateContact(mTransactionContext.get(), db, rawContactId1); 44825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateContact(mTransactionContext.get(), db, rawContactId2); 4483127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 4484127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 4485127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 4486127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 4487b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4488b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 448970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 4490bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 44913826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 44923826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 4493bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected boolean updateAccountsInBackground(Account[] accounts) { 4494f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 4495e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov boolean accountsChanged = false; 44965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); 44975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 44985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.beginTransaction(); 449970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 450043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> existingAccountsWithDataSets = 450143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro findValidAccountsWithDataSets(Tables.ACCOUNTS); 4502743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 450343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add a row to the ACCOUNTS table (with no data set) for each new account. 4504743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 450543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = new AccountWithDataSet( 450643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro account.name, account.type, null); 450743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!existingAccountsWithDataSets.contains(accountWithDataSet)) { 4508e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 450943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 451043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add an account entry with an empty data set to match the account. 45115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 451243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ", " + RawContacts.ACCOUNT_TYPE + ", " + RawContacts.DATA_SET 451343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ") VALUES (?, ?, ?)", 451443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new String[] { 451543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 451643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 451743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 451843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }); 4519743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 4520743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 452148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 452243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Check each of the existing sub-accounts against the account list. If the owning 452343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // account no longer exists, the sub-account and all its data should be deleted. 452443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro List<AccountWithDataSet> accountsWithDataSetsToDelete = 452543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new ArrayList<AccountWithDataSet>(); 452643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro List<Account> accountList = Arrays.asList(accounts); 452743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : existingAccountsWithDataSets) { 452843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Account owningAccount = new Account( 452943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), accountWithDataSet.getAccountType()); 453043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!accountList.contains(owningAccount)) { 453143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsWithDataSetsToDelete.add(accountWithDataSet); 453243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 453370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 453470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 453543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!accountsWithDataSetsToDelete.isEmpty()) { 4536e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 453743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : accountsWithDataSetsToDelete) { 453843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Log.d(TAG, "removing data for removed account " + accountWithDataSet); 453943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String[] accountParams = new String[] { 454043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 454143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType() 454243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }; 454343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String[] accountWithDataSetParams = accountWithDataSet.getDataSet() == null 454443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ? accountParams 454543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro : new String[] { 454643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 454743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 454843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 454943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }; 455043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String groupsDataSetClause = " AND " + Groups.DATA_SET 455143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 455243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String rawContactsDataSetClause = " AND " + RawContacts.DATA_SET 455343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 4554f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String settingsDataSetClause = " AND " + Settings.DATA_SET 4555f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 455643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 45575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4558e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 4559e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 456043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Groups.ACCOUNT_TYPE + " = ?" + 456143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro groupsDataSetClause, accountWithDataSetParams); 45625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4563e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 4564e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 4565e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "SELECT " + RawContacts._ID + 4566e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4567e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 456843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 456943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause + ")", accountWithDataSetParams); 45705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4571c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "DELETE FROM " + Tables.STREAM_ITEM_PHOTOS + 4572c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItemPhotos.STREAM_ITEM_ID + " IN (" + 4573c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + StreamItems._ID + 4574c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.STREAM_ITEMS + 4575c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItems.RAW_CONTACT_ID + " IN (" + 4576c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + RawContacts._ID + 4577c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.RAW_CONTACTS + 4578c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4579c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 4580c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro rawContactsDataSetClause + "))", 4581c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro accountWithDataSetParams); 4582c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro db.execSQL( 4583c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "DELETE FROM " + Tables.STREAM_ITEMS + 4584c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItems.RAW_CONTACT_ID + " IN (" + 4585c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + RawContacts._ID + 4586c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.RAW_CONTACTS + 4587c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4588c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 4589c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro rawContactsDataSetClause + ")", 4590c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro accountWithDataSetParams); 4591c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro db.execSQL( 4592e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 4593e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 459443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 459543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause, accountWithDataSetParams); 45965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4597e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 4598e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 4599f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro " AND " + Settings.ACCOUNT_TYPE + " = ?" + 4600f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsDataSetClause, accountWithDataSetParams); 46015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4602e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 4603e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 460443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + "=?" + 460543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause, accountWithDataSetParams); 46065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4607d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov "DELETE FROM " + Tables.DIRECTORIES + 4608d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " WHERE " + Directory.ACCOUNT_NAME + "=?" + 460943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Directory.ACCOUNT_TYPE + "=?", accountParams); 46104458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov resetDirectoryCache(); 4611e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 4612e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 461333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 461433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 4615e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov // names or photos. If so, fix up those contacts. 461633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 46175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = db.rawQuery("SELECT " + Contacts._ID + 461833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 461933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 462069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 462169cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 462269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 462333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 462433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 462569cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 462669cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 462733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 462833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 462933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 463033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 463133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 463233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 463333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 463433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 463533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 46365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateAggregateData(mTransactionContext.get(), contactId); 463733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 46385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateAllVisible(); 4639bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 464033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 464133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 464243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Now that we've done the account-based additions and subtractions from the Accounts 464343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // table, check for raw contacts that have been added with a data set and add Accounts 464443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // entries for those if necessary. 464543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro existingAccountsWithDataSets = findValidAccountsWithDataSets(Tables.ACCOUNTS); 464643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> rawContactAccountsWithDataSets = 464743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro findValidAccountsWithDataSets(Tables.RAW_CONTACTS); 464843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactAccountsWithDataSets.removeAll(existingAccountsWithDataSets); 464943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 465043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Any remaining raw contact sub-accounts need to be added to the Accounts table. 465143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : rawContactAccountsWithDataSets) { 465243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsChanged = true; 465343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 465443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add an account entry to match the raw contact. 46555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 465643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ", " + RawContacts.ACCOUNT_TYPE + ", " + RawContacts.DATA_SET 465743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ") VALUES (?, ?, ?)", 465843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new String[] { 465943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 466043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 466143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 466243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }); 466343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 466443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 4665e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (accountsChanged) { 466643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO: Should sync state take data set into consideration? 46675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getSyncState().onAccountsChanged(db, accounts); 4668e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 46695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.setTransactionSuccessful(); 467070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 46715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.endTransaction(); 467270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 467373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 46743826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 46753826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (accountsChanged) { 46763826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateContactsAccountCount(accounts); 46773826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 46783826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46793826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 4680afb84050536a4472c13efc0e996d31132d254605Dmitri Plotnikov return accountsChanged; 468170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4682619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 46833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateContactsAccountCount(Account[] accounts) { 46843826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov int count = 0; 46853826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov for (Account account : accounts) { 46863826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (isContactsAccount(account)) { 46873826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov count++; 46883826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46893826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46903826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mContactsAccountCount = count; 46913826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46923826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 46933826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov protected boolean isContactsAccount(Account account) { 46943826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov final IContentService cs = ContentResolver.getContentService(); 46953826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov try { 46963826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return cs.getIsSyncable(account, ContactsContract.AUTHORITY) > 0; 46973826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } catch (RemoteException e) { 46983826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov Log.e(TAG, "Cannot obtain sync flag for account: " + account, e); 46993826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return false; 47003826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 47013826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 47023826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 470372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPackageChanged(String packageName) { 4704bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_DIRECTORIES, packageName); 4705d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4706d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4707619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 470843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Finds all distinct account types and data sets present in the specified table. 4709627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 471043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private Set<AccountWithDataSet> findValidAccountsWithDataSets(String table) { 471143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> accountsWithDataSets = new HashSet<AccountWithDataSet>(); 47125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().rawQuery( 471343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro "SELECT DISTINCT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 471443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro "," + RawContacts.DATA_SET + 471543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " FROM " + table, null); 4716627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4717627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 471891abbc9f691297594262d1f2d79acb744a66712cDave Santoro if (!c.isNull(0) && !c.isNull(1)) { 471943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsWithDataSets.add( 472043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new AccountWithDataSet(c.getString(0), c.getString(1), c.getString(2))); 4721627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4722627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4723627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 4724627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 4725627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 472643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro return accountsWithDataSets; 4727627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4728627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 47294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 47304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 47314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 473215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 473315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mReadAccessLatch); 473415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 47355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Query the profile DB if appropriate. 47365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 47375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 47385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileProvider.query(uri, projection, selection, selectionArgs, sortOrder); 47395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 47405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 47415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Otherwise proceed with a normal query against the contacts DB. 47425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 47435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mContactsHelper.getReadableDatabase()); 4744d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY); 4745385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directory == null) { 4746b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 47475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1)); 4748385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directory.equals("0")) { 4749b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 47503716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 47515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Directory.DEFAULT)); 4752d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } else if (directory.equals("1")) { 4753b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 47543716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 47555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Directory.LOCAL_INVISIBLE)); 4756d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4757d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4758d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryInfo directoryInfo = getDirectoryAuthority(directory); 4759d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo == null) { 4760a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov Log.e(TAG, "Invalid directory ID: " + uri); 4761a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov return null; 4762d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4763d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4764d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Builder builder = new Uri.Builder(); 4765d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.scheme(ContentResolver.SCHEME_CONTENT); 4766d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.authority(directoryInfo.authority); 4767d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.encodedPath(uri.getEncodedPath()); 4768d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountName != null) { 4769d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, directoryInfo.accountName); 4770d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4771d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountType != null) { 4772d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, directoryInfo.accountType); 4773d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 47742e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 47752e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limit = getLimit(uri); 47762e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov if (limit != null) { 47772e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov builder.appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, limit); 47782e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov } 47792e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 4780d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Uri directoryUri = builder.build(); 478109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 478209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (projection == null) { 478309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov projection = getDefaultProjection(uri); 478409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 478509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 4786332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov Cursor cursor = getContext().getContentResolver().query(directoryUri, projection, selection, 4787d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs, sortOrder); 47886ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 47896ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (cursor == null) { 47906ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 47916ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 47926ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 4793547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro CrossProcessCursor crossProcessCursor = getCrossProcessCursor(cursor); 4794547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (crossProcessCursor != null) { 4795b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, cursor); 4796547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } else { 4797b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return matrixCursorFromCursor(addSnippetExtrasToCursor(uri, cursor)); 4798547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 47993716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 48003716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 4801b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private Cursor addSnippetExtrasToCursor(Uri uri, Cursor cursor) { 4802547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 4803547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro // If the cursor doesn't contain a snippet column, don't bother wrapping it. 4804547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (cursor.getColumnIndex(SearchSnippetColumns.SNIPPET) < 0) { 4805b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 4806547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 4807547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 48083716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Parse out snippet arguments for use when snippets are retrieved from the cursor. 48093716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String[] args = null; 48103716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String snippetArgs = 48113716f1447ceb21180d1301790eabd8b9453f486dDave Santoro getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 48123716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (snippetArgs != null) { 48133716f1447ceb21180d1301790eabd8b9453f486dDave Santoro args = snippetArgs.split(","); 48143716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 48153716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 48163716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String query = uri.getLastPathSegment(); 48173716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String startMatch = args != null && args.length > 0 ? args[0] 48183716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_START_MATCH; 48193716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String endMatch = args != null && args.length > 1 ? args[1] 48203716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_END_MATCH; 48213716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String ellipsis = args != null && args.length > 2 ? args[2] 48223716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_ELLIPSIS; 48233716f1447ceb21180d1301790eabd8b9453f486dDave Santoro int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 48243716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 48253716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 4826b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Snippet data is needed for the snippeting on the client side, so store it in the cursor 4827b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (cursor instanceof AbstractCursor && deferredSnippetingRequested(uri)){ 4828b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle oldExtras = cursor.getExtras(); 4829b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle extras = new Bundle(); 4830b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (oldExtras != null) { 4831b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putAll(oldExtras); 4832b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4833b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putString(ContactsContract.DEFERRED_SNIPPETING_QUERY, query); 4834b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 4835b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson ((AbstractCursor) cursor).setExtras(extras); 48365517770250b3afa4fd88b6869c3244680821d222Dave Santoro } 4837b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 4838b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4839b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 4840b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private Cursor addDeferredSnippetingExtra(Cursor cursor) { 4841b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (cursor instanceof AbstractCursor){ 4842b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle oldExtras = cursor.getExtras(); 4843b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle extras = new Bundle(); 4844b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (oldExtras != null) { 4845b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putAll(oldExtras); 4846b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4847b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putBoolean(ContactsContract.DEFERRED_SNIPPETING, true); 4848b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson ((AbstractCursor) cursor).setExtras(extras); 4849b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4850b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 48516ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48526ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 48536ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov private CrossProcessCursor getCrossProcessCursor(Cursor cursor) { 48546ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov Cursor c = cursor; 48556ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (c instanceof CrossProcessCursor) { 48566ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return (CrossProcessCursor) c; 48576ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else if (c instanceof CursorWindow) { 48586ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return getCrossProcessCursor(((CursorWrapper) c).getWrappedCursor()); 48596ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else { 48606ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 48616ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48626ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48636ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 48646ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public MatrixCursor matrixCursorFromCursor(Cursor cursor) { 48656ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 48666ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov int numColumns = cursor.getColumnCount(); 48676ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov String data[] = new String[numColumns]; 48686ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov cursor.moveToPosition(-1); 48696ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov while (cursor.moveToNext()) { 48706ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov for (int i = 0; i < numColumns; i++) { 48716ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov data[i] = cursor.getString(i); 48726ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48736ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov newCursor.addRow(data); 4874332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov } 48756ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return newCursor; 4876d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4877d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4878d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final class DirectoryQuery { 4879d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 4880d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory._ID, 4881d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.DIRECTORY_AUTHORITY, 4882d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_NAME, 4883d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_TYPE 4884d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov }; 4885d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4886d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int DIRECTORY_ID = 0; 4887d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int AUTHORITY = 1; 4888d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_NAME = 2; 4889d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_TYPE = 3; 4890d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4891d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4892d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 4893d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Reads and caches directory information for the database. 4894d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 4895d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private DirectoryInfo getDirectoryAuthority(String directoryId) { 48964458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized (mDirectoryCache) { 48974458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (!mDirectoryCacheValid) { 48984458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.clear(); 48995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getReadableDatabase(); 490049d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Cursor cursor = db.query(Tables.DIRECTORIES, 49014458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryQuery.COLUMNS, 49024458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov null, null, null, null, null); 49034458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov try { 49044458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov while (cursor.moveToNext()) { 49054458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryInfo info = new DirectoryInfo(); 49064458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov String id = cursor.getString(DirectoryQuery.DIRECTORY_ID); 49074458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.authority = cursor.getString(DirectoryQuery.AUTHORITY); 49084458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME); 49094458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE); 49104458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.put(id, info); 49114458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 49124458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } finally { 49134458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov cursor.close(); 4914d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 49154458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = true; 4916d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4917d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 49184458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov return mDirectoryCache.get(directoryId); 49194458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 4920d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4921d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 492272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void resetDirectoryCache() { 49234458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized(mDirectoryCache) { 49244458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = false; 49254458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 492672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 492772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 49285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro protected Cursor queryLocal(Uri uri, String[] projection, String selection, 49295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String[] selectionArgs, String sortOrder, long directoryId) { 4930bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 4931bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 4932bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 49330b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 49345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 49355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 49365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 49375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 493835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4939d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 49401f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 4941c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 4942b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean snippetDeferred = false; 4943c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 49442ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // The expression used in bundleLetterCountExtras() to get count. 49452ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki String addressBookIndexerCountExpression = null; 49462ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 4947a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 49484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 494935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 49505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 49515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().query(mActiveDb.get(), projection, selection, 49525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs, sortOrder); 495335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4954d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 4955763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 49564b64b6e8f448938434cb1e022a4e7dfaae8f9c8cMakoto Onuki appendLocalDirectorySelectionIfNeeded(qb, directoryId); 4957619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 4958619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4959619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4960d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 49614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 4962763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 49634da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 49644da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 49656bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 49666bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 49676bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 49685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 49695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 49705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 49715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 49725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 49735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 4974fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 49755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 4976a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 49775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 49785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 49795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 49805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4981763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 4982a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 49835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 4984a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4985a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 4986a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 49875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 49885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4991763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 49924da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 49935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey))); 49944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 49955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 49965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49982149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_DATA: 4999bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_DATA: 5000bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_PHOTO: 5001bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_PHOTO: { 50022149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 50032149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov int segmentCount = pathSegments.size(); 50042149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount < 4) { 50055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 50062149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov "Missing a lookup key", uri)); 50072149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50082149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String lookupKey = pathSegments.get(2); 50092149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount == 5) { 50102149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 50112149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 50122149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(lookupQb, uri, projection, false); 5013bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (match == CONTACTS_LOOKUP_PHOTO || match == CONTACTS_LOOKUP_ID_PHOTO) { 5014bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 5015bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 5016a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 50175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 5018a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 5019a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey); 5020a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 50212149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov return c; 50222149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50232149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50242149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov // TODO see if the contact exists but has no data rows (rare) 50252149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50262149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50272149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 50285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 50292149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 503024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 5031bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (match == CONTACTS_LOOKUP_PHOTO || match == CONTACTS_LOOKUP_ID_PHOTO) { 5032bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 5033bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 50342149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov qb.appendWhere(" AND " + Data.CONTACT_ID + "=?"); 50352149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov break; 50362149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50372149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_ID_STREAM_ITEMS: { 50393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(uri.getPathSegments().get(1)); 50403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 50413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 5042af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann qb.appendWhere(StreamItems.CONTACT_ID + "=?"); 50433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 50443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 50463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_STREAM_ITEMS: 50473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_ID_STREAM_ITEMS: { 50483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<String> pathSegments = uri.getPathSegments(); 50493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int segmentCount = pathSegments.size(); 50503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount < 4) { 50515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 50523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann "Missing a lookup key", uri)); 50533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String lookupKey = pathSegments.get(2); 50553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount == 5) { 50563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(pathSegments.get(3)); 50573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 50583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(lookupQb); 50595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 50603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann projection, selection, selectionArgs, sortOrder, groupBy, limit, 5061af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann StreamItems.CONTACT_ID, contactId, 5062af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann StreamItems.CONTACT_LOOKUP_KEY, lookupKey); 50633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c != null) { 50643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return c; 50653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 50683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 50695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 50703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 50713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(RawContacts.CONTACT_ID + "=?"); 50723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 50733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 5075f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 507642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 50775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 5078ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 5079f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 50804da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 508124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 50824da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 5083f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 5084f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 5085f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 508642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 508742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 508842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 50895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().rawQuery( 509042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 509142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 509242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 509342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 509442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 509542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 5096ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 5097916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 5098b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean deferredSnipRequested = deferredSnippetingRequested(uri); 5099ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 5100916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 5101ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 51027ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet( 5103b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson qb, uri, projection, filterParam, directoryId, 5104b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnipRequested); 5105b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson snippetDeferred = isSingleWordQuery(filterParam) && 5106b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnipRequested && snippetNeeded(projection); 5107ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5108ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5109ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 5110ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 5111ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 51122f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Basically the resultant SQL should look like this: 51132f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing starred items) 51142f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 51152f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing frequently contacted items) 51162f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // ORDER BY ... 51172f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 51182f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final boolean phoneOnly = readBooleanQueryParameter( 51192f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa uri, ContactsContract.STREQUENT_PHONE_ONLY, false); 51202f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (match == CONTACTS_STREQUENT_FILTER && uri.getPathSegments().size() > 3) { 51214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 51224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5123e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 51245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 51252f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa selection = DbQueryUtils.concatenateClauses(selection, sb.toString()); 51264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 51274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 51282f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] subProjection = null; 51295e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 51302f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa subProjection = appendProjectionArg(projection, TIMES_USED_SORT_COLUMN); 51315e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 51325e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 51334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 51344928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false); 51354928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(phoneOnly ? 51364928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa sStrequentPhoneOnlyStarredProjectionMap 51374928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa : sStrequentStarredProjectionMap); 51389dbfd650ccf93714f3266e80f9fbdbcb526ae7b3Daisuke Miyakawa if (phoneOnly) { 51395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(DbQueryUtils.concatenateClauses( 51405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, Contacts.HAS_PHONE_NUMBER + "=1")); 51419dbfd650ccf93714f3266e80f9fbdbcb526ae7b3Daisuke Miyakawa } 51422f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 51432f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String starredQuery = qb.buildQuery(subProjection, 514424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Contacts.STARRED + "=1", Contacts._ID, null, null, null); 5145d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 51462f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Reset the builder. 5147d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 51482f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 51494928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 51504928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // Build the second query for frequent part. 51514928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa final String frequentQuery; 51524928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa if (phoneOnly) { 51534928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa final StringBuilder tableBuilder = new StringBuilder(); 51544928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // In phone only mode, we need to look at view_data instead of 51554928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // contacts/raw_contacts to obtain actual phone numbers. One problem is that 51564928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // view_data is much larger than view_contacts, so our query might become much 51574928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // slower. 51584928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // 51594928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // To avoid the possible slow down, we start from data usage table and join 51604928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // view_data to the table, assuming data usage table is quite smaller than 51614928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // data rows (almost always it should be), and we don't want any phone 51624928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // numbers not used by the user. This way sqlite is able to drop a number of 51634928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // rows in view_data in the early stage of data lookup. 51644928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa tableBuilder.append(Tables.DATA_USAGE_STAT 51654928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + " INNER JOIN " + Views.DATA + " " + Tables.DATA 51664928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" 51674928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataColumns.CONCRETE_ID + " AND " 51684928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" 51694928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT_CALL + ")"); 51704928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa appendContactPresenceJoin(tableBuilder, projection, RawContacts.CONTACT_ID); 51714928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa appendContactStatusUpdateJoin(tableBuilder, projection, 51724928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa ContactsColumns.LAST_STATUS_UPDATE_ID); 51734928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 51744928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setTables(tableBuilder.toString()); 51754928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(sStrequentPhoneOnlyFrequentProjectionMap); 51764928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 51774928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa selection, 51784928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa Contacts.STARRED + "=0 OR " + Contacts.STARRED + " IS NULL", 51794928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa MimetypesColumns.MIMETYPE + " IN (" 51804928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + "'" + Phone.CONTENT_ITEM_TYPE + "', " 51814928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + "'" + SipAddress.CONTENT_ITEM_TYPE + "')")); 51824928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa frequentQuery = qb.buildQuery(subProjection, null, null, null, null, null); 51834928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa } else { 51844928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, true); 51854928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(sStrequentFrequentProjectionMap); 51864928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 51874928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa selection, 51885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "(" + Contacts.STARRED + " =0 OR " + Contacts.STARRED + " IS NULL)")); 51894928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa frequentQuery = qb.buildQuery(subProjection, 51904928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa null, Contacts._ID, null, null, null); 51914928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa } 5192d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 5193d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 51942f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String unionQuery = 51952f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 51962f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa STREQUENT_ORDER_BY, STREQUENT_LIMIT); 51972f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 51982f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Here, we need to use selection / selectionArgs (supplied from users) "twice", 51992f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // as we want them both for starred items and for frequently contacted items. 52002f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // 52012f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // e.g. if the user specify selection = "starred =?" and selectionArgs = "0", 52022f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // the resultant SQL should be like: 52032f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 52042f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 52052f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 52062f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] doubledSelectionArgs = null; 52072f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (selectionArgs != null) { 52082f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final int length = selectionArgs.length; 52092f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa doubledSelectionArgs = new String[length * 2]; 52107d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, 0, length); 52117d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, length, length); 52122f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 52132f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 52145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().rawQuery(unionQuery, doubledSelectionArgs); 52152f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (cursor != null) { 52162f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa cursor.setNotificationUri(getContext().getContentResolver(), 5217d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 5218d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 52192f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa return cursor; 5220d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 5221d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 522245ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa case CONTACTS_FREQUENT: { 522345ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, true); 522445ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa qb.setProjectionMap(sStrequentFrequentProjectionMap); 522545ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa groupBy = Contacts._ID; 522645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa if (!TextUtils.isEmpty(sortOrder)) { 522745ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa sortOrder = FREQUENT_ORDER_BY + ", " + sortOrder; 522845ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } else { 522945ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa sortOrder = FREQUENT_ORDER_BY; 523045ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } 523145ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa break; 523245ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } 523345ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa 5234ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 5235763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 5236b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 523771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 52387cf50494501938f175d288077145acf49da8f171Daniel Lehmann String groupMimeTypeId = String.valueOf( 52397cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 52404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 52417cf50494501938f175d288077145acf49da8f171Daniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, groupMimeTypeId); 5242b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5243b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 5244b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5245b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 524624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 524724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 524824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 524924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 525024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 525124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: { 525224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForEntities(qb, uri, projection); 525324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 525424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 525524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 525624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: { 5257ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 525824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.setProjectionMap(sContactsVCardProjectionMap); 525924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 526024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 526124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 5262a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_DATA: { 52634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 526482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 52654da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 52664da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 52676bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 52686bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 526900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 5270a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 52713653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 527282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 52734da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 52744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 52753653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 52763653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 52773653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 52783653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 5279a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_ENTITIES: { 5280a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 5281a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 5282a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 5283a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 5284a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 5285a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5286a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5287a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ENTITIES: 5288a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ID_ENTITIES: { 5289a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 5290a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov int segmentCount = pathSegments.size(); 5291a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount < 4) { 52925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 5293a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov "Missing a lookup key", uri)); 5294a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5295a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lookupKey = pathSegments.get(2); 5296a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount == 5) { 5297a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 5298a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 5299a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(lookupQb, uri, projection); 5300a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 5301a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 53025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 5303a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 5304a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.CONTACT_ID, contactId, 5305a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.LOOKUP_KEY, lookupKey); 5306a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 5307a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 5308a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5309a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5310a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5311a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 5312a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 53135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey))); 5314a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?"); 5315a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 5316a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5317a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 53183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 53193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 53203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 53243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 53253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 53269b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann qb.appendWhere(StreamItems._ID + "=?"); 53273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_LIMIT: { 53316802030a777c0c3ba1dc029c534cca4784260632Dave Santoro MatrixCursor cursor = new MatrixCursor(new String[]{StreamItems.MAX_ITEMS}, 1); 53326802030a777c0c3ba1dc029c534cca4784260632Dave Santoro cursor.addRow(new Object[]{MAX_STREAM_ITEMS_PER_RAW_CONTACT}); 53333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return cursor; 53343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 53373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 53383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 53423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 53433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 53443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 53453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?"); 53463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 53503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 53513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 53523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 53533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemPhotoId); 53543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 53553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=? AND " + 53563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=?"); 53573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 5360f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case PHOTO_DIMENSIONS: { 5361f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro MatrixCursor cursor = new MatrixCursor( 5362f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{DisplayPhoto.DISPLAY_MAX_DIM, DisplayPhoto.THUMBNAIL_MAX_DIM}, 5363f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1); 5364f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro cursor.addRow(new Object[]{mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim}); 5365f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return cursor; 5366f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 5367f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 53684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 536982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 53707cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + "=" + 53717cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeIdForPhone()); 53722ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 53732ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // Dedupe phone numbers per contact. 5374cf55cbe8932f620484a3634d13ecc116c32fdc99Daisuke Miyakawa groupBy = RawContacts.CONTACT_ID + ", " + Data.DATA1; 53752ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 53762ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // In this case, because we dedupe phone numbers, the address book indexer needs 53772ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // to take it into account too. (Otherwise headers will appear in wrong positions.) 53782ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // So use count(distinct pair(CONTACT_ID, PHONE NUMBER)) instead of count(*). 53792ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // But because there's no such thing as pair() on sqlite, we use 53802ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // CONTACT_ID || ',' || PHONE NUMBER instead. 53812ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // This only slows down the query by 14% with 10,000 contacts. 53822ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki addressBookIndexerCountExpression = "DISTINCT " 53832ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki + RawContacts.CONTACT_ID + "||','||" + Data.DATA1; 53842815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 53852815f58f72f109790585931f601a63ddc02536a5Evan Millar } 53862815f58f72f109790585931f601a63ddc02536a5Evan Millar 538748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 538882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 53894da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 53907cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 53917cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForPhone()); 53924da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 539348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 539448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 539548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 5396ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 539746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 539846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 539946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 540046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_CALL; 540146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 540246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 54037cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54047cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForPhone()); 5405ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 54064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 54074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5408a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 54095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 541045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 54115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 54125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 54135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 5414155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN " + 5415155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 5416155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 5417155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5418155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 5419155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 5420155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE " + SearchIndexColumns.NAME + " MATCH "); 54212352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filterParam) + "*"); 5422155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(")"); 54235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 542445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 54255e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 5427892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filterParam); 5428892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (!TextUtils.isEmpty(number)) { 54295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 54305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 54315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 5433892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov " IN (SELECT DISTINCT " + PhoneLookupColumns.DATA_ID 5434892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 5435892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 5436892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append(number); 5437892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append("%')"); 543845d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 543945d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 544045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 544145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 544245d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 544345d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 544445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 54455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 5447a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 5448ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 544958567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa groupBy = "(CASE WHEN " + PhoneColumns.NORMALIZED_NUMBER 545058567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa + " IS NOT NULL THEN " + PhoneColumns.NORMALIZED_NUMBER 545158567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa + " ELSE " + Phone.NUMBER + " END), " + RawContacts.CONTACT_ID; 5452a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 545346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 545446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 545546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + PHONE_FILTER_SORT_ORDER; 545646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 545746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = PHONE_FILTER_SORT_ORDER; 545846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 5459a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 5460ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5461ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5462ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 54634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 546482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54657cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54667cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail()); 54674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 54684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 54694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 547048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 547182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 54737cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54747cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail() 54754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 547648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 547748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 547848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 54795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 548082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54817cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54827cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail()); 54834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 548408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 54855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String address = mDbHelper.get().extractAddressFromEmailAddress(email); 548608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 548708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 54884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 5489ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5490ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5491ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 54925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 549346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 549446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 549546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 549646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT; 549746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 549846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 549907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 55007d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa 550107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 550207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 550307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 550407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 550507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 550607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 55075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 550807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 550907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 551007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 551107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 551207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 551307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 551407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 551507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 551607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 55172a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "="); 55185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro sb.append(mDbHelper.get().getMimeTypeIdForEmail()); 55192a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(" AND " + Data.DATA1 + " LIKE "); 552007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 552120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 5522155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append( 5523155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " UNION SELECT " + Data._ID + 5524155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.DATA + 5525155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "="); 55265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro sb.append(mDbHelper.get().getMimeTypeIdForEmail()); 5527155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(" AND " + Data.RAW_CONTACT_ID + " IN " + 5528155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 5529155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 5530155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5531155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 5532155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 5533155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE " + SearchIndexColumns.NAME + " MATCH "); 55342352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filterParam) + "*"); 5535155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(")"); 55365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 5538a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 55395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 5541a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 554246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 554346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 554446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + EMAIL_FILTER_SORT_ORDER; 55457d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } else { 55467d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa sortOrder = EMAIL_FILTER_SORT_ORDER; 55477d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } 5548a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 55495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 55505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 5552ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 555382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55547cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 55557cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForStructuredPostal()); 5556ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5557ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5558ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 555948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 556082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 55627cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 55637cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForStructuredPostal()); 55644da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 556548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 556648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 556748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 5568d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 5569d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 5570763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 55714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 55724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 55734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 5574d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_ID: 5575d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID: { 55765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 5577763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 55784da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 55794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 55804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 55814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 55824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 5583d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 5584d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 5585d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 5586d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(segment)); 558782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55884da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 55894da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 559024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 559124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 559224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 55933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 55943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 55953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 55963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 55973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=?"); 55983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 55993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 560024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 560182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 560282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 560382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro long streamItemId = Long.parseLong(uri.getPathSegments().get(3)); 560482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro setTablesAndProjectionMapForStreamItems(qb); 560582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(streamItemId)); 5606c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 560782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=? AND " + 560882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems._ID + "=?"); 560982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro break; 561082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 561182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 561224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID_ENTITIES: { 561324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(2)); 561424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 561524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForRawEntities(qb, uri); 56165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(" AND " + RawContacts._ID + "=?"); 5617e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 5618e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 5619e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 5620d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case DATA: 5621d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA: { 562282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 5623e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 5624e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 5625e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 5626d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case DATA_ID: 5627d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA_ID: { 562882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 56294da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 56304da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 5631a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 5632a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 5633a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 5634a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 56354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5636a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 5637a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 5638a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 5639892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sortOrder = " length(lookup.normalized_number) DESC"; 5640a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 5641a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5642e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 5643e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov String numberE164 = PhoneNumberUtils.formatNumberToE164(number, 56445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getCurrentCountryIso()); 5645892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String normalizedNumber = 5646892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.normalizeNumber(number); 56475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().buildPhoneLookupAndContactQuery(qb, normalizedNumber, numberE164); 5648e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 5649e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 5650e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 5651e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 5652a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 5653a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 5654a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5655ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 5656ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 5657ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 5658f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5659ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5660ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5661ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5662ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 5663ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 5664ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 56654da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 56664da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 5667ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5668ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5669ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5670ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 5671f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa final boolean returnGroupCountPerAccount = 5672f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa readBooleanQueryParameter(uri, Groups.PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT, 5673f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa false); 5674f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa qb.setTables(Views.GROUPS + " AS " + Tables.GROUPS); 5675f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa qb.setProjectionMap(returnGroupCountPerAccount ? 5676f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa sGroupsSummaryProjectionMapWithGroupCountPerAccount 5677f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa : sGroupsSummaryProjectionMap); 5678f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5679f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa groupBy = GroupsColumns.CONCRETE_ID; 5680ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5681ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5682ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5683b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 56840c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 5685b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 5686b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 5687b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 5688b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 568931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 5690d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 56912d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 56922d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 56932d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 56942d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 569531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 5696d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 5697d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 569831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 569931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 570031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 570131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 57025b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ArrayList<AggregationSuggestionParameter> parameters = null; 57035b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov List<String> query = uri.getQueryParameters("query"); 57045b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov if (query != null && !query.isEmpty()) { 57055b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters = new ArrayList<AggregationSuggestionParameter>(query.size()); 57065b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov for (String parameter : query) { 57075b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov int offset = parameter.indexOf(':'); 57085b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters.add(offset == -1 57095b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ? new AggregationSuggestionParameter( 571076dfa406e2cde19c824983c37fc92c1c5bf63eecDaniel Lehmann AggregationSuggestions.PARAMETER_MATCH_NAME, 57115b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter) 57125b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov : new AggregationSuggestionParameter( 57135b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(0, offset), 57145b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(offset + 1))); 57155b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 57165b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 57175b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 5718763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 57197581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 57205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mAggregator.get().queryAggregationSuggestions(qb, projection, contactId, 57215b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov maxSuggestions, filter, parameters); 572231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 572331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 5724eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 5725eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 5726eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 5727f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5728e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 5729e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 5730e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 57315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final String groupMembershipMimetypeId = Long.toString(mDbHelper.get() 5732e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 573382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 57345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().isInProjection(projection, Settings.UNGROUPED_COUNT)) { 5735e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 5736e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 573782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 57385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().isInProjection( 57395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro projection, Settings.UNGROUPED_WITH_PHONES)) { 5740e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 5741e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 5742e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 5743eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 5744eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 5745eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 57465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 57475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 57480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 57495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 57505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 57515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 575282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 57530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 57544da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 57554da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 57565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 57575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 57585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 5759c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 5760174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery( 57615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get(), uri, projection, limit); 5762c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5763c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 5764c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 57652d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 5766174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String filter = getQueryParameter( 5767174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov uri, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); 5768174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh( 57695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get(), projection, lookupKey, filter); 5770c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5771c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 57721b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 5773ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 57751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 5778ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57791b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 57801b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 57811b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57821b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57831b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 5784ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57851b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 57861b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 57871b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57881b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 5790ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 579271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 57937cf50494501938f175d288077145acf49da8f171Daniel Lehmann String groupMimeTypeId = String.valueOf( 57947cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 57951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 57967cf50494501938f175d288077145acf49da8f171Daniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, groupMimeTypeId); 57971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57981b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57993202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro case RAW_CONTACT_ENTITIES: 58003202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro case PROFILE_RAW_CONTACT_ENTITIES: { 5801a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 580246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 580346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 580446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 580546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 580646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 5807a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 58084da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 58094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 581046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 581146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 581246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 581309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 581409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 581509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 581609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5817d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES : { 5818d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5819d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5820d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5821d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5822d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 5823d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID : { 5824385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov long id = ContentUris.parseId(uri); 5825d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5826d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5827385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(id)); 5828d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Directory._ID + "=?"); 5829d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5830d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5831d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 58327a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov case COMPLETE_NAME: { 58337a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return completeName(uri, projection); 58347a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 58357a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 58364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 5837f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 5838c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 58394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 58404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 584109e69522745551522c55dff27424496f255def46Daniel Lehmann qb.setStrict(true); 58427f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 5843ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 58445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro query(mActiveDb.get(), qb, projection, selection, selectionArgs, sortOrder, groupBy, 58455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro limit); 5846ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 58475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cursor = bundleLetterCountExtras(cursor, mActiveDb.get(), qb, selection, 58482ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki selectionArgs, sortOrder, addressBookIndexerCountExpression); 5849ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5850b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (snippetDeferred) { 5851b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson cursor = addDeferredSnippetingExtra(cursor); 5852b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 5853ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 58545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 58555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 58565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 58575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 58585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 5859038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 5860038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 5861038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 5862038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 58635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 58645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 58654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 58664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 58674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 58684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 58694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 58704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 587109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 587209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 587309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 587409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 587509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 587609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 587709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 587809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 587909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 588009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 588109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 588209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 588309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 588409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 588509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 588609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5887a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 5888a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Runs the query with the supplied contact ID and lookup ID. If the query succeeds, 5889a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * it returns the resulting cursor, otherwise it returns null and the calling 5890a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * method needs to resolve the lookup key and rerun the query. 5891a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 5892a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private Cursor queryWithContactIdAndLookupKey(SQLiteQueryBuilder lookupQb, 5893a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteDatabase db, Uri uri, 5894a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection, String selection, String[] selectionArgs, 5895a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String sortOrder, String groupBy, String limit, 5896a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn, long contactId, String lookupKeyColumn, String lookupKey) { 5897a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] args; 5898a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (selectionArgs == null) { 5899a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[2]; 5900a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 5901a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[selectionArgs.length + 2]; 5902a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 5903a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5904a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[0] = String.valueOf(contactId); 5905a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[1] = Uri.encode(lookupKey); 5906a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(contactIdColumn + "=? AND " + lookupKeyColumn + "=?"); 5907a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 5908a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov groupBy, limit); 5909a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c.getCount() != 0) { 5910a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 5911a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5912a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5913a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov c.close(); 5914a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return null; 5915a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 591609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5917bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 5918bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 5919bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 5920bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 5921ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5922bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 5923bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 5924ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 5925ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5926bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 5927bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 5928bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 5929bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 59305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // The first letter of the sort key column is what is used for the index headings. 59315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public static final String SECTION_HEADING = "SUBSTR(%1$s,1,1)"; 593224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 5933de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 5934ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5935ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5936ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 5937ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 5938ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 5939ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 5940ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 59412ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder, 59422ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki String countExpression) { 5943409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki if (!(cursor instanceof AbstractCursor)) { 5944409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki Log.w(TAG, "Unable to bundle extras. Cursor is not AbstractCursor."); 5945409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki return cursor; 5946409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki } 5947ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 5948ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5949ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 5950ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 5951ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 5952ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 5953ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 5954ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 5955ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 5956ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 5957ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 5958ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 5959ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 5960ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5961ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 5962ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 5963ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5964ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5965bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 5966ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 59675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String sectionHeading = String.format(AddressBookIndexQuery.SECTION_HEADING, sortKey); 5968bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 596924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro sectionHeading + " AS " + AddressBookIndexQuery.LETTER); 5970bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 59712ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // If "what to count" is not specified, we just count all records. 59722ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki if (TextUtils.isEmpty(countExpression)) { 59732ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki countExpression = "*"; 59742ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki } 59752ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 5976bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 5977bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 5978bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 5979bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 5980bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 5981bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 5982bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 5983ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 598424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "GET_PHONEBOOK_INDEX(" + sectionHeading + ",'" + locale + "')" 5985bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 5986ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 59872ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki "COUNT(" + countExpression + ") AS " + AddressBookIndexQuery.COUNT); 5988ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 5989ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5990f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 5991ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 5992ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 5993ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5994ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 5995f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 5996ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 5997ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 5998bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 5999bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 6000bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 6001bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 6002bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 6003bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 6004ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 6005f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 6006bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 6007bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 6008bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 6009bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 6010bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 6011bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 6012bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 6013bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 6014bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 6015bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 6016bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 6017bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 6018bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 6019bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 6020bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 6021bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 6022bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 6023bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 6024bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 6025ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6026ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6027409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki final Bundle bundle = new Bundle(); 6028409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 6029409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 6030409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki 6031409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki ((AbstractCursor) cursor).setExtras(bundle); 6032409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki return cursor; 6033ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 6034f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 6035ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6036ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6037ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 60382d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 603992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 604092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 604192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 604292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 60432d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 60442d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 60455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 60465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 60475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 604892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 60495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_PROFILE)) { 60505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // We should already be in a profile database context, so just look up a single contact. 60515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro contactId = lookupSingleContactId(db); 60525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 605492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 605592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 605692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 605792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 605892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 605992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 606092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 606192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 606292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 606392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 606492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 606592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 606692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 606792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 606892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 606992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 607092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 607192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 60725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 60735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 60765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private long lookupSingleContactId(SQLiteDatabase db) { 60795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = db.query(Tables.CONTACTS, new String[] {Contacts._ID}, 60805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null, null, null, null, null, "1"); 60815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro try { 60825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (c.moveToFirst()) { 60835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return c.getLong(0); 60845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 60855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return -1; 60865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } finally { 60885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c.close(); 60895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 60925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 609343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String TABLE = Views.RAW_CONTACTS; 60945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 60965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 609743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 60985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 60995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 61005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 61015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 610343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 61045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 61055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 61065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 61095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 61105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 61115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 61125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 61135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 611492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 61155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 61165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 61175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 61205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 61215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 61235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 61245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 61255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 612643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = 612743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE_AND_DATA_SET); 61285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 61295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 613043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 61315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 61325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 61335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 613492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 613592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 61365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 61375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 61385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 61395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 61435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 61445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 61475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 614992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 615043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String TABLE = Views.RAW_CONTACTS; 61515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 61535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 615443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 61555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 615692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 61575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 61585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 616043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 61615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 616292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 61635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 616592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 616692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 616792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 616892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 61695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 61705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 617192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 617292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 617392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 61745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 617692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 617792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 61785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 617992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 618092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 618192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 618292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 618343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = c.getString( 618443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro LookupByRawContactIdQuery.ACCOUNT_TYPE_AND_DATA_SET); 618592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 618692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 618743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 618892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 618992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 619092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 619192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 619292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 619392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 619492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 619592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 619692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 619792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 619892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 619992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 620092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 62015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 620392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 620492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 620592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 620692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 620792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 620892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 620992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 621092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 621143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 621292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 621392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 621492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 621592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 621692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 621743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 621892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 621992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 622092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 622192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 622292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 622392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 62245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 62255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 62265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 62275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 622892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 622992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 62305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 62315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 62325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 62355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 62365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 62375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 62395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 62405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 62415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 624243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = 624343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE_AND_DATA_SET); 62445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 62455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 624643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 62475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 62485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 62495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 625092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 625192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 625292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 62535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 62545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 62555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 62565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 62605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 62615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 62645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 626692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 626792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 626892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 626992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 627092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 627192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 627292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 627392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 627492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 627592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 627692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 6277ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 62785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLookupKeyForRawContact(db, rawContactId); 6279ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 6280ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 62815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 62825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 62835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 62845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 62855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 62865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 62885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 62895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 62915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 62925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 62945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 62955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 62965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 62975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 62985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 62995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 63005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 63015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 63025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 63035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 63055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 63065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 63105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 63115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 63125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 63135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 6316763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 6317763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 63184928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false); 63192f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 63202f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 63212f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 63224928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * @param includeDataUsageStat true when the table should include DataUsageStat table. 63234928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Note that this uses INNER JOIN instead of LEFT OUTER JOIN, so some of data in Contacts 63244928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * may be dropped. 63252f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 63262f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 63274928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa String[] projection, boolean includeDataUsageStat) { 632882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6329ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 63302f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 63312f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Just for frequently contacted contacts in Strequent Uri handling. 63324928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa if (includeDataUsageStat) { 63332f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa sb.append(" INNER JOIN " + 6334ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA_USAGE_STAT + " AS " + Tables.DATA_USAGE_STAT + 63352f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa " ON (" + 63362f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DbQueryUtils.concatenateClauses( 63372f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DataUsageStatColumns.CONCRETE_TIMES_USED + " > 0", 63384928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa RawContacts.CONTACT_ID + "=" + Views.CONTACTS + "." + Contacts._ID) + 63392f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa ")"); 63402f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 63412f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 63427ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 63437ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6344916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 6345916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 6346916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 6347916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6348916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 6349916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 6350916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 6351916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 6352916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 6353b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson String[] projection, String filter, long directoryId, boolean deferredSnippeting) { 63547ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov 63557ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 6356ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 6357916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 635803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (filter != null) { 635903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov filter = filter.trim(); 636003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 636103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 636230cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov if (TextUtils.isEmpty(filter) || (directoryId != -1 && directoryId != Directory.DEFAULT)) { 636330cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov sb.append(" JOIN (SELECT NULL AS " + SearchSnippetColumns.SNIPPET + " WHERE 0)"); 63645e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } else { 6365b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson appendSearchIndexJoin(sb, uri, projection, filter, deferredSnippeting); 63665e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 63677ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 63687ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 636903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setTables(sb.toString()); 637003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 637103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 6372916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 637303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private void appendSearchIndexJoin( 6374b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson StringBuilder sb, Uri uri, String[] projection, String filter, 6375b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean deferredSnippeting) { 6376916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6377b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (snippetNeeded(projection)) { 637803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String[] args = null; 637903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String snippetArgs = 638003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 638103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (snippetArgs != null) { 638203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov args = snippetArgs.split(","); 638303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 638403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 63855e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String startMatch = args != null && args.length > 0 ? args[0] 63865e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_START_MATCH; 63875e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String endMatch = args != null && args.length > 1 ? args[1] 63885e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_END_MATCH; 63895e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String ellipsis = args != null && args.length > 2 ? args[2] 63905e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_ELLIPSIS; 63915e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 63925e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 63935e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 6394174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov appendSearchIndexJoin( 6395b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson sb, filter, true, startMatch, endMatch, ellipsis, maxTokens, 6396b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnippeting); 6397174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 6398b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson appendSearchIndexJoin(sb, filter, false, null, null, null, 0, false); 6399174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6400174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6401174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 6402174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov public void appendSearchIndexJoin(StringBuilder sb, String filter, 6403174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean snippetNeeded, String startMatch, String endMatch, String ellipsis, 6404b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson int maxTokens, boolean deferredSnippeting) { 6405174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isEmailAddress = false; 6406174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String emailAddress = null; 6407174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isPhoneNumber = false; 6408174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String phoneNumber = null; 6409174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String numberE164 = null; 6410174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 64113716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // If the query consists of a single word, we can do snippetizing after-the-fact for a 64123716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // performance boost. 6413b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean singleTokenSearch = isSingleWordQuery(filter); 64143716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6415174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (filter.indexOf('@') != -1) { 64165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro emailAddress = mDbHelper.get().extractAddressFromEmailAddress(filter); 6417174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isEmailAddress = !TextUtils.isEmpty(emailAddress); 6418174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 6419174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isPhoneNumber = isPhoneNumber(filter); 642004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (isPhoneNumber) { 642104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann phoneNumber = PhoneNumberUtils.normalizeNumber(filter); 642204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann numberE164 = PhoneNumberUtils.formatNumberToE164(phoneNumber, 64235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getCountryIso()); 642404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 6425174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6426174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 6427174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov sb.append(" JOIN (SELECT " + SearchIndexColumns.CONTACT_ID + " AS snippet_contact_id"); 6428174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (snippetNeeded) { 64295e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(", "); 64305e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 64313d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 64325e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 643304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Email.ADDRESS + ")"); 643404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS); 643504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 643604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID + " AND " + Email.ADDRESS + " LIKE "); 643704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann DatabaseUtils.appendEscapedSQLString(sb, filter + "%"); 643804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 64393d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 64403d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(","); 64413716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6442b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested). 6443b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 64443716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 64453716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 64463716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 64473716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 64483d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(")"); 64493d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 64503d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 64513d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 645204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Phone.NUMBER + ")"); 645304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + 645404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann Tables.DATA_JOIN_RAW_CONTACTS + " JOIN " + Tables.PHONE_LOOKUP); 645504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" ON " + DataColumns.CONCRETE_ID); 645604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + Tables.PHONE_LOOKUP + "." + PhoneLookupColumns.DATA_ID); 645704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 645804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID); 645904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" AND " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 646004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(phoneNumber); 646104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 646204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(numberE164)) { 646304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" OR " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 646404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(numberE164); 646504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 646604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 646704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 64685e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 64695e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 64703716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6471b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested). 6472b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 64733716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 64743716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 64753716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 64763716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 64775e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 647803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 647904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann final String normalizedFilter = NameNormalizer.normalize(filter); 648004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(normalizedFilter)) { 6481b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested).. 6482b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 64833716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 64843716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 64853716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("(CASE WHEN EXISTS (SELECT 1 FROM "); 64863716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.RAW_CONTACTS + " AS rc INNER JOIN "); 64873716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.NAME_LOOKUP + " AS nl ON (rc." + RawContacts._ID); 64883716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=nl." + NameLookupColumns.RAW_CONTACT_ID); 64893716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") WHERE nl." + NameLookupColumns.NORMALIZED_NAME); 64903716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" GLOB '" + normalizedFilter + "*' AND "); 64913716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("nl." + NameLookupColumns.NAME_TYPE + "="); 64923716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(NameLookupType.NAME_COLLATION_KEY + " AND "); 64933716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 64943716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=rc." + RawContacts.CONTACT_ID); 64953716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") THEN NULL ELSE "); 64963716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 64973716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" END)"); 64983716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 649904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } else { 650004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("NULL"); 650104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 650203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 65035e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" AS " + SearchSnippetColumns.SNIPPET); 65045e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 650503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 65065e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" FROM " + Tables.SEARCH_INDEX); 65075e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" WHERE "); 65085e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(Tables.SEARCH_INDEX + " MATCH "); 65095e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 65102352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, "\"" + sanitizeMatch(filter) + "*\""); 65113d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 65122352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, 651304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann "\"" + sanitizeMatch(filter) + "*\" OR \"" + phoneNumber + "*\"" 65142352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov + (numberE164 != null ? " OR \"" + numberE164 + "\"" : "")); 651503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 65162352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filter) + "*"); 65179c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 651803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(") ON (" + Contacts._ID + "=snippet_contact_id)"); 6519a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov } 6520a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov 65212352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov private String sanitizeMatch(String filter) { 65222352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov // TODO more robust preprocessing of match expressions 65232352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov return filter.replace('-', ' ').replace('\"', ' '); 65242352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov } 65252352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov 65265e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov private void appendSnippetFunction( 65275e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov StringBuilder sb, String startMatch, String endMatch, String ellipsis, int maxTokens) { 65285e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append("snippet(" + Tables.SEARCH_INDEX + ","); 65295e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 65305e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 65315e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 65325e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 65335e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, ellipsis); 65345e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 65355e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov // The index of the column used for the snippet, "content" 65365e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(",1,"); 65375e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(maxTokens); 65385e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 65395e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 65405e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 6541763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 6542763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 6543ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.RAW_CONTACTS); 6544763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 6545763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 6546f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6547763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 6548763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 6549a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForRawEntities(SQLiteQueryBuilder qb, Uri uri) { 6550ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.RAW_ENTITIES); 6551a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sRawEntityProjectionMap); 6552f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 655346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 655446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 655582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 655682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 655746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, distinct, null); 655846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 655946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 656046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 656146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @param usageType when non-null {@link Tables#DATA_USAGE_STAT} is joined with the specified 656246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type. 656346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 656446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 656546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String[] projection, boolean distinct, Integer usageType) { 656682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6567ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 656882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 656982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 6570a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, RawContacts.CONTACT_ID); 6571a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6572a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 6573a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 65743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 657546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (usageType != null) { 657646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa appendDataUsageStatJoin(sb, usageType, DataColumns.CONCRETE_ID); 657746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 657846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 657982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 6580f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 6581f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov boolean useDistinct = distinct 65825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro || !mDbHelper.get().isInProjection(projection, DISTINCT_DATA_PROHIBITING_COLUMNS); 6583f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setDistinct(useDistinct); 6584f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setProjectionMap(useDistinct ? sDistinctDataProjectionMap : sDataProjectionMap); 6585f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6586ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 6587ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 65880a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 65890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 65900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6591ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 65920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 6593a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 6594a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 65950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 6596a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 6597a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 6598a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6599a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 66003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItems(SQLiteQueryBuilder qb) { 66019b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann qb.setTables(Views.STREAM_ITEMS); 66023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemsProjectionMap); 66033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 66043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 66053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItemPhotos(SQLiteQueryBuilder qb) { 66061dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro qb.setTables(Tables.PHOTO_FILES 66071dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + " JOIN " + Tables.STREAM_ITEM_PHOTOS + " ON (" 66081dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + StreamItemPhotosColumns.CONCRETE_PHOTO_FILE_ID + "=" 66091dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + PhotoFilesColumns.CONCRETE_ID 66101dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + ") JOIN " + Tables.STREAM_ITEMS + " ON (" 66111dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=" 66120bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + StreamItemsColumns.CONCRETE_ID + ")" 66130bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + " JOIN " + Tables.RAW_CONTACTS + " ON (" 66140bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + StreamItemsColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID 66150bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + ")"); 66163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemPhotosProjectionMap); 66173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 66183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 6619a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForEntities(SQLiteQueryBuilder qb, Uri uri, 6620a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection) { 6621a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 6622ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.ENTITIES); 6623a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" data"); 6624a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6625a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts.Entity.CONTACT_ID); 6626a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6627a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, Contacts.Entity.DATA_ID); 6628a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, Contacts.Entity.DATA_ID); 6629a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6630a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 6631a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sEntityProjectionMap); 6632f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6633a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6634a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6635a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactStatusUpdateJoin(StringBuilder sb, String[] projection, 6636a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lastStatusUpdateIdColumn) { 66375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 6638a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS, 6639a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 6640a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 6641a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 6642a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 6643a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 6644a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 6645a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + lastStatusUpdateIdColumn + "=" 6646a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 66470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 6648a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 66490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 6650a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataStatusUpdateJoin(StringBuilder sb, String[] projection, 6651a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 66525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 66530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 66540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 66550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 66560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 66570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 66580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 6659a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 6660a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + dataIdColumn + ")"); 66610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 6662a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6663a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 666446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void appendDataUsageStatJoin(StringBuilder sb, int usageType, String dataIdColumn) { 666546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" LEFT OUTER JOIN " + Tables.DATA_USAGE_STAT + 666646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" + dataIdColumn + 666746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " AND " + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" + usageType + ")"); 666846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 666946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 6670a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactPresenceJoin(StringBuilder sb, String[] projection, 6671a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn) { 66725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 6673a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_PRESENCE, Contacts.CONTACT_CHAT_CAPABILITY)) { 6674a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 6675a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + contactIdColumn + " = " 6676a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + ")"); 6677a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6678a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6679a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6680a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataPresenceJoin(StringBuilder sb, String[] projection, 6681a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 66825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, Data.PRESENCE, Data.CHAT_CAPABILITY)) { 6683a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 6684a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdates.DATA_ID + "=" + dataIdColumn + ")"); 6685a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6686a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6687a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 668824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private boolean appendLocalDirectorySelectionIfNeeded(SQLiteQueryBuilder qb, long directoryId) { 6689385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directoryId == Directory.DEFAULT) { 6690385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " IN " + Tables.DEFAULT_DIRECTORY); 669124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 6692385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directoryId == Directory.LOCAL_INVISIBLE){ 6693385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " NOT IN " + Tables.DEFAULT_DIRECTORY); 669424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 669524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 669624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return false; 669724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 669824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 6699f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 6700f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 6701f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 670243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro final String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 6703e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6704e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 6705e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 6706e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 67075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6708fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 6709e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 6710e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6711e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 6712e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 6713e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 6714e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 671543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String toAppend = RawContacts.ACCOUNT_NAME + "=" 67164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 67174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 671843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + DatabaseUtils.sqlEscapeString(accountType); 6719f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet == null) { 6720f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro toAppend += " AND " + RawContacts.DATA_SET + " IS NULL"; 6721f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } else { 6722f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro toAppend += " AND " + RawContacts.DATA_SET + "=" + 6723f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro DatabaseUtils.sqlEscapeString(dataSet); 672443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 672543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro qb.appendWhere(toAppend); 67264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 67274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 67284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 67294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 67304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 6731e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 6732f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 6733f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 673443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro final String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 6735e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6736e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 6737e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 6738e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 67395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6740fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 6741e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 6742e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6743e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 6744e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 6745e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 6746e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 6747e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 6748e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 6749e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 6750e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 6751f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet == null) { 6752f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro selectionSb.append(" AND " + RawContacts.DATA_SET + " IS NULL"); 6753f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } else { 675443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro selectionSb.append(" AND " + RawContacts.DATA_SET + "=") 675543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .append(DatabaseUtils.sqlEscapeString(dataSet)); 675643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 6757e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 6758e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 6759e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 6760e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 6761e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6762e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 6763e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 6764e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 6765e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6766e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6767e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 67687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 6769c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 6770c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 6771c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 6772c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 6773c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 6774f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 67752e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limitParam = getQueryParameter(uri, ContactsContract.LIMIT_PARAM_KEY); 6776c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 6777c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6778c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6779c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 6780c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 6781c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 6782c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 6783c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 6784c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6785c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6786c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 6787c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 6788c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 6789c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6790c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6791c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6792c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 6793b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 6794f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 6795f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (mode.equals("r")) { 6796f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro waitForAccess(mReadAccessLatch); 6797f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 6798f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro waitForAccess(mWriteAccessLatch); 6799f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 68005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 68015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 68025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileProvider.openAssetFile(uri, mode); 68035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 68045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 68055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mode.equals("r")) { 68065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDb = mDbHelper.get().getReadableDatabase(); 68075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 68085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDb = mDbHelper.get().getWritableDatabase(); 68095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 68105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openAssetFileLocal(uri, mode); 68115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 68125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 68135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 68145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public AssetFileDescriptor openAssetFileLocal(Uri uri, String mode) 68155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throws FileNotFoundException { 68165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 68175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 68185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 68195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 68205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 6821415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 6822b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 6823b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 6824a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 6825bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long contactId = Long.parseLong(uri.getPathSegments().get(1)); 68265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 682724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Data._ID + "=" + Contacts.PHOTO_ID + " AND " + 682824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro RawContacts.CONTACT_ID + "=?", 6829bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro new String[]{String.valueOf(contactId)}); 6830e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 6831b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 6832f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_ID_DISPLAY_PHOTO: { 6833f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6834f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6835f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by contact ID can only be read."); 6836f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6837f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long contactId = Long.parseLong(uri.getPathSegments().get(1)); 68385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.CONTACTS, 6839f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{Contacts.PHOTO_FILE_ID}, 6840f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Contacts._ID + "=?", new String[]{String.valueOf(contactId)}, 6841f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro null, null, null); 6842f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6843f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6844f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = c.getLong(0); 6845f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6846f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6847f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6848f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6849f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6850f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6851bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_PHOTO: 6852bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_PHOTO: 6853f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_DISPLAY_PHOTO: 6854f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_ID_DISPLAY_PHOTO: { 6855f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6856f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6857bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro "Photos retrieved by contact lookup key can only be read."); 6858f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6859f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro List<String> pathSegments = uri.getPathSegments(); 6860f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro int segmentCount = pathSegments.size(); 6861f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (segmentCount < 4) { 68625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6863f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Missing a lookup key", uri)); 6864f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6865bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro 6866bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro boolean forDisplayPhoto = (match == CONTACTS_LOOKUP_ID_DISPLAY_PHOTO 6867bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro || match == CONTACTS_LOOKUP_DISPLAY_PHOTO); 6868f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String lookupKey = pathSegments.get(2); 6869bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro String[] projection = new String[]{Contacts.PHOTO_ID, Contacts.PHOTO_FILE_ID}; 6870f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (segmentCount == 5) { 6871f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long contactId = Long.parseLong(pathSegments.get(3)); 6872f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 6873f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 68745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 6875f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro projection, null, null, null, null, null, 6876f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 6877f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (c != null) { 6878f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6879f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6880bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (forDisplayPhoto) { 6881bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoFileId = 6882bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro c.getLong(c.getColumnIndex(Contacts.PHOTO_FILE_ID)); 6883bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openDisplayPhotoForRead(photoFileId); 6884bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } else { 6885bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoId = c.getLong(c.getColumnIndex(Contacts.PHOTO_ID)); 6886bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 6887bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro Data._ID + "=?", new String[]{String.valueOf(photoId)}); 6888bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 6889f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6890f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6891f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6892f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6893f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6894f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6895f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 6896f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 68975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 68985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), projection, Contacts._ID + "=?", 6899f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{String.valueOf(contactId)}, null, null, null); 6900f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6901f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6902bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (forDisplayPhoto) { 6903bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoFileId = c.getLong(c.getColumnIndex(Contacts.PHOTO_FILE_ID)); 6904bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openDisplayPhotoForRead(photoFileId); 6905bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } else { 6906bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoId = c.getLong(c.getColumnIndex(Contacts.PHOTO_ID)); 6907bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 6908bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro Data._ID + "=?", new String[]{String.valueOf(photoId)}); 6909bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 6910f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6911f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6912f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6913f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6914f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6915f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case RAW_CONTACTS_ID_DISPLAY_PHOTO: { 6916f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 6917f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro boolean writeable = !mode.equals("r"); 6918f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6919f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Find the primary photo data record for this raw contact. 6920f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 6921f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String[] projection = new String[]{Data._ID, Photo.PHOTO_FILE_ID}; 6922f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 69237cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 69245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), projection, 69257cf50494501938f175d288077145acf49da8f171Daniel Lehmann Data.RAW_CONTACT_ID + "=? AND " + DataColumns.MIMETYPE_ID + "=?", 69267cf50494501938f175d288077145acf49da8f171Daniel Lehmann new String[]{String.valueOf(rawContactId), String.valueOf(photoMimetypeId)}, 6927f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro null, null, Data.IS_PRIMARY + " DESC"); 6928f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long dataId = 0; 6929f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = 0; 6930f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6931f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (c.getCount() >= 1) { 6932f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6933f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro dataId = c.getLong(0); 6934f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro photoFileId = c.getLong(1); 6935f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6936f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6937f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6938f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6939f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6940f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // If writeable, open a writeable file descriptor that we can monitor. 6941f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // When the caller finishes writing content, we'll process the photo and 6942f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // update the data record. 6943f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (writeable) { 6944f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForWrite(rawContactId, dataId, uri, mode); 6945f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 6946f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6947f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6948f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6949f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6950f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case DISPLAY_PHOTO: { 6951f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = ContentUris.parseId(uri); 6952f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6953f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6954f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by key can only be read."); 6955f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6956f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6957f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6958f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6959e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 696024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long dataId = Long.parseLong(uri.getPathSegments().get(1)); 69617cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 69625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 69637cf50494501938f175d288077145acf49da8f171Daniel Lehmann Data._ID + "=? AND " + DataColumns.MIMETYPE_ID + "=" + photoMimetypeId, 696424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro new String[]{String.valueOf(dataId)}); 6965d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 6966d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 6967fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case PROFILE_AS_VCARD: { 6968fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // When opening a contact as file, we pass back contents as a 6969fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // vCard-encoded stream. We build into a local buffer first, 6970fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // then pipe into MemoryFile once the exact size is known. 6971fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6972fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 6973fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen return buildAssetFileDescriptor(localStream); 6974fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen } 697542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 6976fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case CONTACTS_AS_VCARD: { 697742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 697842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 697942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 698042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6981fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 6982f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 698342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 698442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 698542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 698642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 698742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 698842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 6989fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Uri queryUri = Contacts.CONTENT_URI; 699042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 6991fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen 6992d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 6993d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 699442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 699542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 6996d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 699742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 6998d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 699942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 70005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // TODO: Figure out what to do if the profile contact is in the list. 70015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 700224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro inBuilder.append(contactId); 700342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 700442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 700542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 700642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 7007d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7008d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 7009d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 7010d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 7011d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 7012fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(queryUri, localStream, selection, null); 7013f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 7014d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7015b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 7016b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 70175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new FileNotFoundException(mDbHelper.get().exceptionMessage( 70185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "File does not exist", uri)); 7019b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 7020b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 7021b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 7022afc8e7ad6e5208db6c87b8500ecc1246ad966d62Dave Santoro private AssetFileDescriptor openPhotoAssetFile(SQLiteDatabase db, Uri uri, String mode, 7023afc8e7ad6e5208db6c87b8500ecc1246ad966d62Dave Santoro String selection, String[] selectionArgs) 7024e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 7025e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 70265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new FileNotFoundException(mDbHelper.get().exceptionMessage("Mode " + mode 7027e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 7028e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 7029e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 7030e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 7031ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann "SELECT " + Photo.PHOTO + " FROM " + Views.DATA + 7032e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 703308ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood try { 7034f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 7035f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert DatabaseUtils.blobFileDescriptorForQuery(db, sql, selectionArgs)); 703608ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } catch (SQLiteDoneException e) { 703708ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood // this will happen if the DB query returns no rows (i.e. contact does not exist) 703808ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood throw new FileNotFoundException(uri.toString()); 703908ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } 7040e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 7041e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 7042f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7043f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Opens a display photo from the photo store for reading. 7044f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param photoFileId The display photo file ID 7045f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @return An asset file descriptor that allows the file to be read. 7046f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @throws FileNotFoundException If no photo file for the given ID exists. 7047f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7048f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private AssetFileDescriptor openDisplayPhotoForRead(long photoFileId) 7049f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throws FileNotFoundException { 70505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore.Entry entry = mPhotoStore.get().get(photoFileId); 7051f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (entry != null) { 7052f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return makeAssetFileDescriptor( 7053f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ParcelFileDescriptor.open(new File(entry.path), 7054f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ParcelFileDescriptor.MODE_READ_ONLY), 7055f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro entry.size); 7056f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 7057f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 7058f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new FileNotFoundException("No photo file found for ID " + photoFileId); 7059f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7060f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7061f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7062f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7063f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Opens a file descriptor for a photo to be written. When the caller completes writing 7064f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * to the file (closing the output stream), the image will be parsed out and processed. 7065f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * If processing succeeds, the given raw contact ID's primary photo record will be 7066f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * populated with the inserted image (if no primary photo record exists, the data ID can 7067f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * be left as 0, and a new data record will be inserted). 7068f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param rawContactId Raw contact ID this photo entry should be associated with. 7069f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param dataId Data ID for a photo mimetype that will be updated with the inserted 7070f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * image. May be set to 0, in which case the inserted image will trigger creation 7071f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * of a new primary photo image data row for the raw contact. 7072f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param uri The URI being used to access this file. 7073f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param mode Read/write mode string. 7074f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @return An asset file descriptor the caller can use to write an image file for the 7075f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * raw contact. 7076f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7077f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private AssetFileDescriptor openDisplayPhotoForWrite(long rawContactId, long dataId, Uri uri, 7078f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String mode) { 7079f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7080c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro ParcelFileDescriptor[] pipeFds = ParcelFileDescriptor.createPipe(); 7081c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro PipeMonitor pipeMonitor = new PipeMonitor(rawContactId, dataId, pipeFds[0]); 7082c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro pipeMonitor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[]) null); 7083c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro return new AssetFileDescriptor(pipeFds[1], 0, AssetFileDescriptor.UNKNOWN_LENGTH); 7084f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } catch (IOException ioe) { 7085f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Log.e(TAG, "Could not create temp image file in mode " + mode); 7086f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return null; 7087f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7088f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7089f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7090f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7091c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * Async task that monitors the given file descriptor (the read end of a pipe) for 7092c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * the writer finishing. If the data from the pipe contains a valid image, the image 7093c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * is either inserted into the given raw contact or updated in the given data row. 7094f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7095c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private class PipeMonitor extends AsyncTask<Object, Object, Object> { 7096c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private final ParcelFileDescriptor mDescriptor; 7097f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private final long mRawContactId; 7098f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private final long mDataId; 7099c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private PipeMonitor(long rawContactId, long dataId, ParcelFileDescriptor descriptor) { 7100f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mRawContactId = rawContactId; 7101f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mDataId = dataId; 7102c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro mDescriptor = descriptor; 7103f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7104f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7105f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro @Override 7106c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro protected Object doInBackground(Object... params) { 7107c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro AutoCloseInputStream is = new AutoCloseInputStream(mDescriptor); 7108f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7109c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro Bitmap b = BitmapFactory.decodeStream(is); 7110f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (b != null) { 7111fa4db3db4146a26f154ef2e89352ad70a5415b8eDaniel Lehmann waitForAccess(mWriteAccessLatch); 7112f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro PhotoProcessor processor = new PhotoProcessor(b, mMaxDisplayPhotoDim, 7113f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxThumbnailPhotoDim); 7114f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7115f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Store the compressed photo in the photo store. 71165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore photoStore = ContactsContract.isProfileId(mRawContactId) 71175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ? mProfilePhotoStore 71185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro : mContactsPhotoStore; 71195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long photoFileId = photoStore.insert(processor); 7120f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7121c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro // Depending on whether we already had a data row to attach the photo 7122c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro // to, do an update or insert. 7123f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (mDataId != 0) { 7124f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Update the data record with the new photo. 7125f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues updateValues = new ContentValues(); 7126f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7127f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Signal that photo processing has already been handled. 7128f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 7129f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7130f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (photoFileId != 0) { 7131f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(Photo.PHOTO_FILE_ID, photoFileId); 7132f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7133f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(Photo.PHOTO, processor.getThumbnailPhotoBytes()); 7134c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro update(ContentUris.withAppendedId(Data.CONTENT_URI, mDataId), 7135c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro updateValues, null, null); 7136f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 7137f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Insert a new primary data record with the photo. 7138f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues insertValues = new ContentValues(); 7139f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7140f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Signal that photo processing has already been handled. 7141f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 7142f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7143f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 7144f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Data.IS_PRIMARY, 1); 7145f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (photoFileId != 0) { 7146f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Photo.PHOTO_FILE_ID, photoFileId); 7147f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7148f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Photo.PHOTO, processor.getThumbnailPhotoBytes()); 7149f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insert(RawContacts.CONTENT_URI.buildUpon() 7150f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .appendPath(String.valueOf(mRawContactId)) 7151f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .appendPath(RawContacts.Data.CONTENT_DIRECTORY).build(), 7152f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues); 7153f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7154c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro 7155f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7156c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro } catch (IOException e) { 7157c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro throw new RuntimeException(e); 7158f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7159c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro return null; 7160f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7161f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7162f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7163d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 7164d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7165d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 7166f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert * Returns an {@link AssetFileDescriptor} backed by the 7167d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 7168d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 7169f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 7170d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 7171d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 7172d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7173d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 7174d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7175f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 7176f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert ParcelFileDescriptor.fromData(byteData, CONTACT_MEMORY_FILE_NAME), 7177f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert byteData.length); 7178d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 7179ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert Log.w(TAG, "Problem writing stream into an ParcelFileDescriptor: " + e.toString()); 7180ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return null; 7181d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7182d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7183d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7184f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd) { 7185f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor(fd, AssetFileDescriptor.UNKNOWN_LENGTH); 7186f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 7187f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 7188f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd, long length) { 7189f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return fd != null ? new AssetFileDescriptor(fd, 0, length) : null; 7190f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 7191f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 7192d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 7193d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 7194d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 7195d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 7196d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 7197fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen private void outputRawContactsAsVCard(Uri uri, OutputStream stream, 7198fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen String selection, String[] selectionArgs) { 7199d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 7200dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen int vcardconfig = VCardConfig.VCARD_TYPE_DEFAULT; 7201fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if(uri.getBooleanQueryParameter( 7202fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, false)) { 7203dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen vcardconfig |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT; 7204dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen } 72057a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 7206dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen new VCardComposer(context, vcardconfig, false); 7207108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Writer writer = null; 72083711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen final Uri rawContactsUri; 72093711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen if (mapsToProfileDb(uri)) { 72103711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen rawContactsUri = RawContactsEntity.PROFILE_CONTENT_URI; 72113711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen } else { 72123711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen rawContactsUri = RawContactsEntity.CONTENT_URI; 72133711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen } 7214108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 7215108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer = new BufferedWriter(new OutputStreamWriter(stream)); 72163711af1a5799a7ae0c8e761e13a67a9fb5878cc8Martijn Coenen if (!composer.init(uri, selection, selectionArgs, null, rawContactsUri)) { 7217108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 7218108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return; 7219108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7220d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7221108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa while (!composer.isAfterLast()) { 7222108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.write(composer.createOneEntry()); 7223108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7224108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 7225108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.e(TAG, "IOException: " + e); 7226108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } finally { 7227108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa composer.terminate(); 7228108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa if (writer != null) { 7229108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 7230108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.close(); 7231108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 7232108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "IOException during closing output stream: " + e); 7233108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7234d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7235d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7236d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7237b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 72384f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 72394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 7240415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 7241415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov waitForAccess(mReadAccessLatch); 7242415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 7243a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 72444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 7245b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 7246be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 72472d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 7248b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 7249b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 725024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 7251b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 7252f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 725342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 725424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 7255f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 7256f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov case CONTACTS_ID_PHOTO: 7257bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_PHOTO: 7258bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_PHOTO: 7259f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_ID_DISPLAY_PHOTO: 7260f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_DISPLAY_PHOTO: 7261f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_ID_DISPLAY_PHOTO: 7262f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case RAW_CONTACTS_ID_DISPLAY_PHOTO: 7263f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case DISPLAY_PHOTO: 7264f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return "image/jpeg"; 7265b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 726624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 7267be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 7268b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 726924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 7270b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 7271f481f22a9323fe338672f99b88b26c5f0725cd42David Brown case DATA: 727224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 7273f481f22a9323fe338672f99b88b26c5f0725cd42David Brown return Data.CONTENT_TYPE; 7274508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 72755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long id = ContentUris.parseId(uri); 72765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (ContactsContract.isProfileId(id)) { 72775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getDataMimeType(id); 72785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 72795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mContactsHelper.getDataMimeType(id); 72805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 728148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 728248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 728348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 728448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 72859005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 72869005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 728748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 728848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 728948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 729048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 729148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 729248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 729348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 729448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 7295b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 7296b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 7297b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 7298b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 7299b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 7300b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 7301b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 7302b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 7303c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 7304c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 7305c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 7306c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 7307d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES: 7308d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_TYPE; 7309d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID: 7310d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_ITEM_TYPE; 7311af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS: 7312af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.CONTENT_TYPE; 7313af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID: 7314af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.CONTENT_ITEM_TYPE; 7315af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID_PHOTOS: 7316af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.StreamItemPhotos.CONTENT_TYPE; 7317af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID_PHOTOS_ID: 7318af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.StreamItemPhotos.CONTENT_ITEM_TYPE; 7319af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_PHOTOS: 7320af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki throw new UnsupportedOperationException("Not supported for write-only URI " + uri); 732161efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 732261efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 73234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 73244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 73257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 732609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public String[] getDefaultProjection(Uri uri) { 732709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov final int match = sUriMatcher.match(uri); 732809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov switch (match) { 732909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS: 733009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP: 733109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_ID: 733209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP_ID: 733309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 733424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 733509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsProjectionMap.getColumnNames(); 733609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 73378727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov case CONTACTS_ID_ENTITIES: 733824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: 73398727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov return sEntityProjectionMap.getColumnNames(); 73408727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov 734109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_VCARD: 734209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_MULTI_VCARD: 734324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 734409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsVCardProjectionMap.getColumnNames(); 734509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 734609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS: 734709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS_ID: 734824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 734924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 735009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sRawContactsProjectionMap.getColumnNames(); 735109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 735209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DATA_ID: 735309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES: 735409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES_ID: 735509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS: 735609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS_ID: 735709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS: 735809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS_ID: 735924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 736009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDataProjectionMap.getColumnNames(); 736109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 736209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONE_LOOKUP: 736309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sPhoneLookupProjectionMap.getColumnNames(); 736409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 736509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 736609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 736709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sAggregationExceptionsProjectionMap.getColumnNames(); 736809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 736909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case SETTINGS: 737009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sSettingsProjectionMap.getColumnNames(); 737109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 737209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES: 737309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES_ID: 737409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDirectoryProjectionMap.getColumnNames(); 737509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 737609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov default: 737709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return null; 737809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 737909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 738009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 7381f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 7382f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7383f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 7384f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 7385f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7386f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7387f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 7388f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 7389f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 73905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().insertNameLookup(rawContactId, dataId, lookupType, name); 7391f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7392f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7393f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 7394f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 7395d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 7396f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7397f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7398f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 73992d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 7400d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 7401d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 7402d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 7403d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 7404d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 7405d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 7406d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 7407e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 7408916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 7409916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 7410e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 7411e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 74129a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov public boolean isPhoneNumber(String filter) { 74139a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean atLeastOneDigit = false; 74149a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov int len = filter.length(); 74159a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov for (int i = 0; i < len; i++) { 74169a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov char c = filter.charAt(i); 74179a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (c >= '0' && c <= '9') { 74189a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov atLeastOneDigit = true; 74199a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } else if (c != '*' && c != '#' && c != '+' && c != 'N' && c != '.' && c != ';' 74209a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov && c != '-' && c != '(' && c != ')' && c != ' ') { 74219a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 74229a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 74239a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 74249a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return atLeastOneDigit; 74259a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 74269a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 74274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 74287a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * Takes components of a name from the query parameters and returns a cursor with those 74297a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * components as well as all missing components. There is no database activity involved 74307a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * in this so the call can be made on the UI thread. 74317a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov */ 74327a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private Cursor completeName(Uri uri, String[] projection) { 74337a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (projection == null) { 74347a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov projection = sDataProjectionMap.getColumnNames(); 74357a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74367a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74377a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ContentValues values = new ContentValues(); 7438f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov DataRowHandlerForStructuredName handler = (DataRowHandlerForStructuredName) 7439f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov getDataRowHandler(StructuredName.CONTENT_ITEM_TYPE); 74407a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74417a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov copyQueryParamsToContentValues(values, uri, 74427a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.DISPLAY_NAME, 74437a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PREFIX, 74447a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.GIVEN_NAME, 74457a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.MIDDLE_NAME, 74467a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.FAMILY_NAME, 74477a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.SUFFIX, 74487a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_NAME, 74497a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_FAMILY_NAME, 74507a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_MIDDLE_NAME, 74517a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_GIVEN_NAME 74527a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ); 74537a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74547a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov handler.fixStructuredNameComponents(values, values); 74557a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74567a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 74577a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov Object[] row = new Object[projection.length]; 74587a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (int i = 0; i < projection.length; i++) { 74597a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov row[i] = values.get(projection[i]); 74607a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74617a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.addRow(row); 74627a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return cursor; 74637a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74647a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74657a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private void copyQueryParamsToContentValues(ContentValues values, Uri uri, String... columns) { 74667a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (String column : columns) { 74677a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String param = uri.getQueryParameter(column); 74687a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (param != null) { 74697a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov values.put(column, param); 74707a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74717a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74727a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74737a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74747a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74757a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov /** 74764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 74774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 74784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 7479b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 7480b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 7481b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 7482b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 7483b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 74844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 74854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 7486b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 7487b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 7488b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 7489caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 74905e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 74915e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 74925e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 74935e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 74945e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 74955e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 74965e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 74975e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 74985e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 74995e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 75005e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 7501caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 7502caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 7503caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 75045f1f4a062ac34d75d2dbf586702cbeb121cf09caDmitri Plotnikov Account[] accounts = accountManager.getAccountsByType(DEFAULT_ACCOUNT_TYPE); 7505caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 7506caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 7507caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 7508caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 75096f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 7510caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 75116f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 7512caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 7513f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 751473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 751543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Returns true if the specified account type and data set is writable. 751673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 751743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro protected boolean isWritableAccountWithDataSet(String accountTypeAndDataSet) { 751843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (accountTypeAndDataSet == null) { 7519bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 7520bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 7521bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 752243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Boolean writable = mAccountWritability.get(accountTypeAndDataSet); 752373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 752473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 752573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 752673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 7527627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 7528627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 752943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO(dsantoro): Need to update this logic to allow for sub-accounts. 7530627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 7531627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 753243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountTypeAndDataSet.equals(sync.accountType)) { 753373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 753473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 7535627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7536627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7537627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 7538627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 7539627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 754073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 754173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 754273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 754373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 754473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 754543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro mAccountWritability.put(accountTypeAndDataSet, writable); 754673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 7547627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7548b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 7549d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 7550f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 7551f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 7552f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7553f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 7554f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 7555f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 7556f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 7557f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7558f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7559f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 7560f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 7561f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 7562f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7563f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7564f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 7565f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7566f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 7567f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 7568f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7569f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7570f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 7571f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 7572f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 7573f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 7574f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 7575f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7576f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7577f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 7578f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 7579f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 7580f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 7581f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 7582f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 7583f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 7584f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7585f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7586f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 7587f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 7588f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7589f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 7590f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 7591f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 7592f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 7593f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 7594f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 75955fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 75965fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa 75975fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // Should match against the whole parameter instead of its suffix. 75985fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // e.g. The parameter "param" must not be found in "some_param=val". 75995fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (index > 0) { 76005fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa char prevChar = query.charAt(index - 1); 76015fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (prevChar != '?' && prevChar != '&') { 76025fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // With "some_param=val1¶m=val2", we should find second "param" occurrence. 76035fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa index += parameterLength; 76045fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa continue; 76055fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 7606f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7607f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7608f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 7609f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7610f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 7611f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 7612f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7613f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7614f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 7615f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 7616f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 7617f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7618f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7619f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7620f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 7621f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 7622f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 7623f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 7624f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 7625f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7626f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7627f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 7628f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 76295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 76300dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov protected boolean isAggregationUpgradeNeeded() { 76310dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 76320dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return false; 76330dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76340dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 76355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int version = Integer.parseInt(mContactsHelper.getProperty( 76365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROPERTY_AGGREGATION_ALGORITHM, "1")); 76370dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return version < PROPERTY_AGGREGATION_ALGORITHM_VERSION; 76380dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76390dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 7640bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void upgradeAggregationAlgorithmInBackground() { 76410dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // This upgrade will affect very few contacts, so it can be performed on the 76420dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // main thread during the initial boot after an OTA 76430dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 76440dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Upgrading aggregation algorithm"); 76450dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int count = 0; 76460dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 76475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = null; 76480dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 76495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 76505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db = mContactsHelper.getWritableDatabase(); 76515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 76525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.beginTransaction(); 76535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = db.query(true, 76540dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Tables.RAW_CONTACTS + " r1 JOIN " + Tables.RAW_CONTACTS + " r2", 76550dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov new String[]{"r1." + RawContacts._ID}, 76560dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov "r1." + RawContacts._ID + "!=r2." + RawContacts._ID + 76570dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.CONTACT_ID + "=r2." + RawContacts.CONTACT_ID + 76580dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_NAME + "=r2." + RawContacts.ACCOUNT_NAME + 765943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND r1." + RawContacts.ACCOUNT_TYPE + "=r2." + RawContacts.ACCOUNT_TYPE + 766043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND r1." + RawContacts.DATA_SET + "=r2." + RawContacts.DATA_SET, 76610dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov null, null, null, null, null); 76620dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 76630dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov while (cursor.moveToNext()) { 76640dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long rawContactId = cursor.getLong(0); 76650dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, 76660dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 76670dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov count++; 76680dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76690dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 76700dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov cursor.close(); 76710dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator.aggregateInTransaction(mTransactionContext.get(), db); 7673bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 76745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.setTransactionSuccessful(); 76755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setProperty(PROPERTY_AGGREGATION_ALGORITHM, 76760dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov String.valueOf(PROPERTY_AGGREGATION_ALGORITHM_VERSION)); 76770dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 76785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (db != null) { 76795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.endTransaction(); 76805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 76810dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 76820dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Aggregation algorithm upgraded for " + count 76830dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov + " contacts, in " + (end - start) + "ms"); 76840dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76850dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76869a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 76879a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov /* Visible for testing */ 76889a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean isPhone() { 76899a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (!sIsPhoneInitialized) { 76909a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhone = new TelephonyManager(getContext()).isVoiceCapable(); 76919a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhoneInitialized = true; 76929a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 76939a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return sIsPhone; 76949a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 769546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 769646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private boolean handleDataUsageFeedback(Uri uri) { 769746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final long currentTimeMillis = System.currentTimeMillis(); 769846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String usageType = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 769946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] ids = uri.getLastPathSegment().trim().split(","); 770046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ArrayList<Long> dataIds = new ArrayList<Long>(); 770146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 770246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (String id : ids) { 770346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa dataIds.add(Long.valueOf(id)); 770446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 770546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final boolean successful; 770646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (TextUtils.isEmpty(usageType)) { 770746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.w(TAG, "Method for data usage feedback isn't specified. Ignoring."); 770846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = false; 770946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 771046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = updateDataUsageStat(dataIds, usageType, currentTimeMillis) > 0; 771146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 771246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 771346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Handle old API. This doesn't affect the result of this entire method. 771446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] questionMarks = new String[ids.length]; 771546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Arrays.fill(questionMarks, "?"); 771646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = Data._ID + " IN (" + TextUtils.join(",", questionMarks) + ")"; 77175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final Cursor cursor = mActiveDb.get().query( 7718ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA, 771946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { Data.CONTACT_ID }, 772046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa where, ids, null, null, null); 772146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 772246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa while (cursor.moveToNext()) { 772346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mSelectionArgs1[0] = cursor.getString(0); 772446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa ContentValues values2 = new ContentValues(); 772546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values2.put(Contacts.LAST_TIME_CONTACTED, currentTimeMillis); 77265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.CONTACTS, values2, Contacts._ID + "=?", 77275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mSelectionArgs1); 77285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 77295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 773046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 773146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 773246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 773346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 773446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 773546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return successful; 773646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 773746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 773846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 773946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Update {@link Tables#DATA_USAGE_STAT}. 774046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * 774146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @return the number of rows affected. 774246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 7743f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa @VisibleForTesting 7744f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa /* package */ int updateDataUsageStat( 7745f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa List<Long> dataIds, String type, long currentTimeMillis) { 774646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final int typeInt = sDataUsageTypeMap.get(type); 774746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = DataUsageStatColumns.DATA_ID + " =? AND " 774846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT + " =?"; 774946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] columns = 775046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { DataUsageStatColumns._ID, DataUsageStatColumns.TIMES_USED }; 775146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ContentValues values = new ContentValues(); 775246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (Long dataId : dataIds) { 775346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] args = new String[] { dataId.toString(), String.valueOf(typeInt) }; 77545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().beginTransaction(); 775546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 77565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final Cursor cursor = mActiveDb.get().query(Tables.DATA_USAGE_STAT, columns, where, 77575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro args, null, null, null); 775846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 775946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (cursor.getCount() > 0) { 776046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!cursor.moveToFirst()) { 776146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.e(TAG, 776246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa "moveToFirst() failed while getAccount() returned non-zero."); 776346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 776446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 776546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, cursor.getInt(1) + 1); 776646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 77675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.DATA_USAGE_STAT, values, 776846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns._ID + " =?", 776946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { cursor.getString(0) }); 777046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 777146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 777246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 777346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.DATA_ID, dataId); 777446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.USAGE_TYPE_INT, typeInt); 777546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, 1); 777646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 77775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().insert(Tables.DATA_USAGE_STAT, null, values); 777846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 77795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().setTransactionSuccessful(); 778046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 778146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 778246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 778346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 77845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().endTransaction(); 778546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 778646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 778746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 778846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return dataIds.size(); 778946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 779046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 779146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 779246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Returns a sort order String for promoting data rows (email addresses, phone numbers, etc.) 779346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * associated with a primary account. The primary account should be supplied from applications 779446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * with {@link ContactsContract#PRIMARY_ACCOUNT_NAME} and 779546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * {@link ContactsContract#PRIMARY_ACCOUNT_TYPE}. Null will be returned when the primary 779646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * account isn't available. 779746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 779846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private String getAccountPromotionSortOrder(Uri uri) { 779946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountName = 780046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_NAME); 780146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountType = 780246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_TYPE); 780346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 780446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Data rows associated with primary account should be promoted. 780546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountName)) { 780646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa StringBuilder sb = new StringBuilder(); 780746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append("(CASE WHEN " + RawContacts.ACCOUNT_NAME + "="); 780846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountName); 780946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountType)) { 781046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" AND " + RawContacts.ACCOUNT_TYPE + "="); 781146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountType); 781246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 781346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" THEN 0 ELSE 1 END)"); 781446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return sb.toString(); 781546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 781646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return null; 781746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 781846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 7819b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 7820b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 7821b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks the URI for a deferred snippeting request 7822b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if a deferred snippeting request is in the RI 7823b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 7824b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean deferredSnippetingRequested(Uri uri) { 7825b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson String deferredSnippeting = 7826b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson getQueryParameter(uri, SearchSnippetColumns.DEFERRED_SNIPPETING_KEY); 7827b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return !TextUtils.isEmpty(deferredSnippeting) && deferredSnippeting.equals("1"); 7828b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 7829b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 7830b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 7831b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks if query is a single word or not. 7832b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if the query is one word or not 7833b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 7834b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean isSingleWordQuery(String query) { 7835b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return query.split(QUERY_TOKENIZER_REGEX).length == 1; 7836b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 7837b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 7838b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 7839b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks the projection for a SNIPPET column indicating that a snippet is needed 7840b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if a snippet is needed or not. 7841b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 7842b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean snippetNeeded(String [] projection) { 7843b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return mDbHelper.get().isInProjection(projection, SearchSnippetColumns.SNIPPET); 7844b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 78454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 7846